//----------------------------------------------------------------------------
// ObjectWindow - OWL NExt
// Copyright 1999. Yura Bidus. All Rights reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// OVERVIEW
// ~~~~~~~~
// Source file for implementation of TCoolGrid (TControl).
// (Generated by OWL 6.x Class Expert for MS VC++, Version 1.5)
//----------------------------------------------------------------------------
#include <coolprj/pch.h>
#pragma hdrstop
#include <owl/scroller.h>
#include <owl/uihelper.h>
#include <owl/uimetric.h>
#include <owl/celarray.h>
#include <algorithm>
using namespace owl;
using namespace std;
#include <coolprj/coolgrid.h>
//#include "resource.h" // Definition of all resources.
//#define USE_AUTOORG
#ifdef WIN32
const int MSB=0x80000000;
#else
const int MSB=0x8000;
#endif
//
const int HitDelta = 2;
//
static TCoolGrid::TCell*
CreateCoolCell(TCoolGrid&, const TCellPos&)
{
return 0;
}
//
static TCoolGrid::TColumn*
CreateCoolColumn(TCoolGrid& grid, int /*loc*/)
{
return new TCoolGrid::TColumn(grid);
}
//
void TCellRange::Normalize()
{
if(srow > erow){
std::swap(srow, erow);
std::swap(scol, ecol);
}
if(srow == erow && scol > ecol)
std::swap(scol, ecol);
}
//
//-------------------------------------------------------------------
// class TCoolGrid::TCellMap
// ~~~~~ ~~~~~~~~~~~~~~~~~~~
//
void TCoolGrid::TCellMap::Flush(bool del)
{
if(del){
for(iterator itr = begin(); itr != end(); itr++)
delete (*itr).second;
}
clear();
}
//
//-------------------------------------------------------------------
// class TCoolGrid::TColumnMap
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~
//
void TCoolGrid::TColumnMap::Flush(bool del)
{
if(del){
for(iterator itr = begin(); itr != end(); itr++)
delete (*itr).second;
}
clear();
}
//-------------------------------------------------------------------
// class TCoolGrid::TInPlaceEdit
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TInPlaceEdit::TInPlaceEdit()
:
ExitOnArrows(false),
LastKey(0)
{
}
//
void TCoolGrid::TInPlaceEdit::EndEdit()
{
GetGrid()->SendMessage(COOLGRID_ENDEDIT);
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TInPlaceEditCtrl
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DEFINE_RESPONSE_TABLE1(TCoolGrid::TInPlaceEditCtrl, TEdit)
EV_WM_CHAR,
EV_WM_KEYDOWN,
EV_WM_KILLFOCUS,
EV_WM_GETDLGCODE,
END_RESPONSE_TABLE;
//
TCoolGrid::TInPlaceEditCtrl::TInPlaceEditCtrl(TCoolGrid& parent, uint textLimit)
:
TEdit(&parent,0,_T(""), 0,0,0,0, textLimit) // default value
{
ModifyStyle(WS_VISIBLE,0);
}
//
TCoolGrid::TInPlaceEditCtrl::~TInPlaceEditCtrl()
{
Destroy(IDCANCEL);
}
//
TCoolGrid* TCoolGrid::TInPlaceEditCtrl::GetGrid()
{
return TYPESAFE_DOWNCAST(GetParentO(), TCoolGrid);
}
//
void TCoolGrid::TInPlaceEditCtrl::EvChar(uint key, uint repeatCount, uint flags)
{
if(key == VK_TAB || key == VK_RETURN || key == VK_ESCAPE){
if(key == VK_ESCAPE)
Undo();
LastKey = key;
GetGrid()->SetFocus();
return;
}
// call base functions
TEdit::EvChar(key, repeatCount, flags);
// Resize edit control if needed
TTmpBuffer<_TCHAR> buff(MAX_PATH);
GetText(buff, MAX_PATH);
// add some extra buffer
_tcscat(buff,_T(" "));
TWindowDC dc(*this);
dc.SelectObject(TFont(GetWindowFont()));
const auto size = dc.GetTextExtentPoint32(&buff[0]);
dc.RestoreFont();
// Get client rect
TRect parentRect;
GetParentO()->GetClientRect(parentRect);
TRect clientRect;
GetClientRect(clientRect);
MapWindowPoints(GetParentH(), (TPoint*)&clientRect, 2);
// Check whether control needs to be resized
// and whether there is space to grow
if (size.cx > clientRect.Width()){
if( size.cx + clientRect.left < parentRect.right)
clientRect.right = clientRect.left + size.cx;
else
clientRect.right = parentRect.right;
MoveWindow(clientRect);
}
}
//
void TCoolGrid::TInPlaceEditCtrl::EvKeyDown(uint key, uint repeatCount, uint flags)
{
if((key==VK_PRIOR||key==VK_NEXT||key==VK_DOWN||key==VK_UP||key==VK_RIGHT||
key==VK_LEFT) && (ExitOnArrows||GetKeyState(VK_CONTROL)<0)){
LastKey = key;
GetGrid()->SetFocus();
return;
}
TEdit::EvKeyDown(key, repeatCount, flags);
}
//
uint TCoolGrid::TInPlaceEditCtrl::EvGetDlgCode(const MSG* msg)
{
return TEdit::EvGetDlgCode(msg)|DLGC_WANTALLKEYS;
}
//
void TCoolGrid::TInPlaceEditCtrl::EvKillFocus(HWND hWndGetFocus)
{
ShowWindow(SW_HIDE);
TEdit::EvKillFocus(hWndGetFocus);
EndEdit();
}
//
void TCoolGrid::TInPlaceEditCtrl::Activate(const TRect& rect, uint firstKey)
{
TCoolGrid* grid = GetGrid();
PRECONDITION(grid);
if(grid->GetFont())
SetWindowFont(*grid->GetFont(), false);
MoveWindow(rect, false);
ExitOnArrows = (firstKey != VK_LBUTTON); // If mouse click brought us here,
// Activate the edit box.
ShowWindow(SW_SHOW);
SetFocus();
switch(firstKey){
case VK_LBUTTON:
case VK_RETURN: {
TTmpBuffer<_TCHAR> buff(MAX_PATH);
GetText(buff, MAX_PATH);
SetSelection((int)_tcslen(buff), -1);
}
return;
case VK_BACK:{
TTmpBuffer<_TCHAR> buff(MAX_PATH);
GetText(buff, MAX_PATH);
SetSelection((int)_tcslen(buff), -1);
}
break;
case VK_TAB: case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT:
case VK_NEXT: case VK_PRIOR: case VK_HOME: case VK_SPACE: case VK_END:
SetSelection(0, -1);
return;
default:
SetSelection(0, -1);
}
SendMessage(WM_CHAR, firstKey);
}
//
uint TCoolGrid::TInPlaceEditCtrl::Transfer(void* buffer, TTransferDirection direction)
{
return TEdit::Transfer(buffer, direction);
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TInPlaceListBox
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DEFINE_RESPONSE_TABLE1(TCoolGrid::TInPlaceListBox, TComboBox)
EV_WM_KEYDOWN,
EV_WM_KILLFOCUS,
EV_WM_GETDLGCODE,
END_RESPONSE_TABLE;
//
TCoolGrid::TInPlaceListBox::TInPlaceListBox(TCoolGrid& parent, uint textLimit)
:
TComboBox(&parent, -1, 0,0,0,0, CBS_DROPDOWNLIST, textLimit)
{
ModifyStyle(WS_VISIBLE|CBS_SORT, 0);
}
//
TCoolGrid::TInPlaceListBox::~TInPlaceListBox()
{
Destroy(IDCANCEL);
}
//
void TCoolGrid::TInPlaceListBox::SetupWindow()
{
TComboBox::SetupWindow();
TComboBox::Transfer(&Data, tdSetData);
}
//
TCoolGrid* TCoolGrid::TInPlaceListBox::GetGrid()
{
return TYPESAFE_DOWNCAST(GetParentO(), TCoolGrid);
}
//
void TCoolGrid::TInPlaceListBox::Activate(const TRect& rect, uint firstKey)
{
TCoolGrid* grid = GetGrid();
PRECONDITION(grid);
if(grid->GetFont())
SetWindowFont(*grid->GetFont(), false);
TRect clientRect(rect);
clientRect.bottom += clientRect.Height()*5;
MoveWindow(clientRect, false);
// ExitOnArrows = (firstKey != VK_LBUTTON); // If mouse click brought us here,
ExitOnArrows = false;
SetDroppedWidth(4);
SetHorizontalExtent(0); // no horz scrolling
// Activate the edit box.
ShowWindow(SW_SHOW);
SetFocus();
PostMessage(WM_CHAR, firstKey);
}
//
uint TCoolGrid::TInPlaceListBox::Transfer(void* buffer, TTransferDirection direction)
{
if (!buffer && direction != tdSizeData) return 0;
if (direction == tdGetData){
GetWindowText((LPTSTR)buffer, TextLimit);
}
else if (direction == tdSetData){
SetWindowText((LPTSTR)buffer);
SetSelString((LPTSTR)buffer, 0);
Data.SelectString((LPTSTR)buffer);
}
return TextLimit;
}
//
inline bool checkExceptKeys(uint key)
{
return (key==VK_TAB||key==VK_RETURN||key==VK_ESCAPE);
}
//
inline bool checkHotListBoxKeys(uint key)
{
return (key==VK_PRIOR||key==VK_NEXT||key==VK_DOWN||key==VK_UP||
key==VK_RIGHT||key==VK_LEFT);
}
//
void TCoolGrid::TInPlaceListBox::EvKeyDown(uint key, uint repeatCount, uint flags)
{
if(checkExceptKeys(key) || (checkHotListBoxKeys(key) &&
(ExitOnArrows||GetKeyState(VK_CONTROL)<0))){
if(key == VK_ESCAPE)
Undo();
LastKey = key;
GetGrid()->SetFocus();
return;
}
TComboBox::EvKeyDown(key, repeatCount, flags);
}
//
uint TCoolGrid::TInPlaceListBox::EvGetDlgCode(const MSG* msg)
{
return TComboBox::EvGetDlgCode(msg)|DLGC_WANTALLKEYS;
}
//
void TCoolGrid::TInPlaceListBox::Undo()
{
SetWindowText(Data.GetSelection().c_str());
}
//
void TCoolGrid::TInPlaceListBox::EvKillFocus(HWND hWndGetFocus)
{
ShowWindow(SW_HIDE);
TComboBox::EvKillFocus(hWndGetFocus);
EndEdit();
}
//------------------------------------------------------------------------
// class TCoolGrid::TInPlaceComboBox::TLocalEdit
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local edit
#define IDC_LOCAL_COMBOEDIT 1001
DEFINE_RESPONSE_TABLE1(TCoolGrid::TInPlaceComboBox::TLocalEdit, TEdit)
EV_WM_KEYDOWN,
EV_WM_CHAR,
EV_WM_KILLFOCUS,
EV_WM_GETDLGCODE,
EV_WM_LBUTTONDBLCLK,
END_RESPONSE_TABLE;
//
TCoolGrid::TInPlaceComboBox::TLocalEdit::TLocalEdit(TWindow* parent, HWND hWnd)
:
TEdit(parent,0,0,0,0,0,0,0)
{
AttachHandle(hWnd);
}
//
TCoolGrid::TInPlaceComboBox*
TCoolGrid::TInPlaceComboBox::TLocalEdit::GetComboBox()
{
return TYPESAFE_DOWNCAST(GetParentO(), TCoolGrid::TInPlaceComboBox);
}
//
inline bool checkHotLocalEditKeys(uint key)
{
return (key==VK_PRIOR||key==VK_NEXT||key==VK_TAB||key==VK_RETURN||
key==VK_ESCAPE||key==VK_DOWN||key==VK_UP||key==VK_RIGHT||
key==VK_LEFT);
}
//
void TCoolGrid::TInPlaceComboBox::TLocalEdit::EvKeyDown(uint key, uint repeatCount, uint flags)
{
TCoolGrid::TInPlaceComboBox* cBox = GetComboBox();
if(checkHotLocalEditKeys(key)){
if(checkExceptKeys(key) || cBox->ExitOnArrows || GetKeyState(VK_CONTROL) < 0){
cBox->HandleMessage(WM_KEYDOWN, key, MkUint32(repeatCount,flags));
return;
}
Inherited::EvKeyDown(key, repeatCount, flags);
}
else if(!cBox->IsReadOnly())
Inherited::EvKeyDown(key, repeatCount, flags);
}
//
void TCoolGrid::TInPlaceComboBox::TLocalEdit::EvChar(uint key, uint repeatCount, uint flags)
{
if(!GetComboBox()->IsReadOnly())
Inherited::EvKeyDown(key, repeatCount, flags);
}
//
uint TCoolGrid::TInPlaceComboBox::TLocalEdit::EvGetDlgCode(const MSG* msg)
{
return Inherited::EvGetDlgCode(msg)|DLGC_WANTALLKEYS;
}
//
void TCoolGrid::TInPlaceComboBox::TLocalEdit::EvKillFocus(HWND hWndGetFocus)
{
TCoolGrid::TInPlaceComboBox* cBox = GetComboBox();
cBox->ShowWindow(SW_HIDE);
Inherited::EvKillFocus(hWndGetFocus);
cBox->EndEdit();
}
//
void TCoolGrid::TInPlaceComboBox::TLocalEdit::EvLButtonDblClk(uint modKeys, const TPoint& point)
{
Inherited::EvLButtonDblClk(modKeys, point);
TComboBox* cbox = GetComboBox();
int index = cbox->GetSelIndex();
if(index==CB_ERR || (index+1) >= cbox->GetCount())
index = -1;
index++;
cbox->SetSelIndex(index);
}
//------------------------------------------------------------------------
// class TCoolGrid::TInPlaceComboBox
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DropDown combobox
//
DEFINE_RESPONSE_TABLE1(TCoolGrid::TInPlaceComboBox, TInPlaceListBox)
EV_WM_KEYDOWN,
EV_WM_KILLFOCUS,
END_RESPONSE_TABLE;
//
TCoolGrid::TInPlaceComboBox::TInPlaceComboBox(TCoolGrid& parent, uint textLimit)
:
TInPlaceListBox(parent, textLimit)
,LocalEdit(0)
,ReadOnly(false)
{
ModifyStyle(CBS_DROPDOWNLIST, CBS_DROPDOWN);
}
//
void TCoolGrid::TInPlaceComboBox::SetupWindow()
{
TListBox::SetupWindow();
SetTextLimit(TextLimit);
THandle hWnd = ::GetWindow(GetHandle(), GW_CHILD);
while (hWnd) {
if(!GetWindowPtr(hWnd)){
TWindow* wnd = 0; InUse(wnd);
if(::GetDlgCtrlID(hWnd)==IDC_LOCAL_COMBOEDIT)
wnd = LocalEdit = new TLocalEdit(this, hWnd);
else
wnd = new TWindow(hWnd);
wnd->SetParent(this);
}
hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
}
TComboBox::Transfer(&Data, tdSetData);
}
//
void TCoolGrid::TInPlaceComboBox::SetReadOnly(bool readonly)
{
ReadOnly = readonly;
if(GetHandle())
LocalEdit->SetReadOnly(ReadOnly);
}
//
void TCoolGrid::TInPlaceComboBox::Activate(const TRect& rect, uint firstKey)
{
// TInPlaceListBox::Activate(rect, firstKey);
TCoolGrid* grid = GetGrid();
PRECONDITION(grid);
if(grid->GetFont())
SetWindowFont(*grid->GetFont(), false);
TRect clientRect(rect);
clientRect.bottom += clientRect.Height()*5;
MoveWindow(clientRect, false);
// ExitOnArrows = (firstKey != VK_LBUTTON); // If mouse click brought us here,
SetDroppedWidth(4);
SetHorizontalExtent(0); // no horz scrolling
// Activate the edit box.
ShowWindow(SW_SHOW);
SetFocus();
switch(firstKey){
case VK_LBUTTON:
case VK_RETURN:{
TTmpBuffer<_TCHAR> buff(MAX_PATH);
LocalEdit->GetText(buff, MAX_PATH);
LocalEdit->SetSelection((int)_tcslen(buff), -1);
}
return;
case VK_BACK:{
TTmpBuffer<_TCHAR> buff(MAX_PATH);
LocalEdit->GetText(buff, MAX_PATH);
LocalEdit->SetSelection((int)_tcslen(buff), -1);
}
break;
case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT:
case VK_NEXT: case VK_PRIOR: case VK_HOME: case VK_END:
LocalEdit->SetSelection(0, -1);
return;
default:
LocalEdit->SetSelection(0, -1);
}
PostMessage(WM_CHAR, firstKey);
}
//
void TCoolGrid::TInPlaceComboBox::EvKillFocus(HWND hWndGetFocus)
{
TComboBox::EvKillFocus(hWndGetFocus);
}
//
inline bool checkHotComboBoxKeys(uint key)
{
return (key==VK_PRIOR||key==VK_NEXT||key==VK_DOWN||key==VK_UP||
key==VK_RIGHT||key==VK_LEFT);
}
//
void TCoolGrid::TInPlaceComboBox::EvKeyDown(uint key, uint repeatCount, uint flags)
{
if(checkExceptKeys(key) || (checkHotComboBoxKeys(key) &&
(ExitOnArrows||GetKeyState(VK_CONTROL)<0))){
if(key == VK_ESCAPE)
Undo();
LastKey = key;
GetGrid()->SetFocus();
return;
}
TComboBox::EvKeyDown(key, repeatCount, flags);
}
//
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TCell
// ~~~~~ ~~~~~~~~~~~~~~~~
//
TCoolGrid::TCell::TCell()
:
Parent(0)
{
}
//
TCoolGrid::TCell::~TCell()
{
}
//
void TCoolGrid::TCell::Paint(TDC& dc, const TRect& rect)
{
TColor oldClr = dc.SetBkColor(TColor::SysWindow);
dc.TextRect(rect);
dc.SetBkColor(oldClr);
}
////////////////////////////////////////////////////////////////////
//
// class TTextCell
// ~~~~~ ~~~~~~~~~
//
TCoolGrid::TTextCell::TTextCell()
:
Text(0),
TextLimit(255),
Format(DT_CENTER|DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_NOCLIP),
BgColor(TColor::SysWindow),
TxColor(TColor::SysWindowText)
{
}
//
TCoolGrid::TTextCell::TTextCell(LPCTSTR text, uint textLimit)
:
Text(0),
TextLimit(textLimit),
Format(DT_CENTER|DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_NOCLIP),
BgColor(TColor::SysWindow),
TxColor(TColor::SysWindowText)
{
SetText(text);
}
//-----------------------------------------------------------------------------
TCoolGrid::TTextCell::TTextCell(const owl::tstring& text, uint textLimit)
:
Text(0),
TextLimit(textLimit),
Format(DT_CENTER|DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS|DT_NOCLIP),
BgColor(TColor::SysWindow),
TxColor(TColor::SysWindowText)
{
SetText(text);
}
//-----------------------------------------------------------------------------
TCoolGrid::TTextCell::~TTextCell()
{
delete[] Text;
}
//
void TCoolGrid::TTextCell::SetText(const owl::tstring& text)
{
SetText(text.c_str());
}
//
void TCoolGrid::TTextCell::SetText(LPCTSTR text)
{
delete[] Text;
Text = text ? strnewdup(text) : 0;
}
//
void TCoolGrid::TTextCell::Paint(TDC& dc, const TRect& rect)
{
PRECONDITION(Parent);
if(!Text){
TCell::Paint(dc, rect);
return;
}
TFont* font = Parent->GetFont();
if(font){
CHECK(font->IsGDIObject());
dc.SelectObject(*font);
}
TColor oldBgClr = dc.SetBkColor(BgColor);
TColor oldTxClr = dc.SetTextColor(TxColor);
dc.TextRect(rect);
TRect r = rect;
dc.DrawTextEx(Text, -1, &r, Format);
dc.SetBkColor(oldBgClr);
dc.SetTextColor(oldTxClr);
if(font)
dc.RestoreFont();
}
//
// Transfers state information for TTextCell
//
// The direction passed specifies whether data is to be read from or
// written to the passed buffer, or whether the data element size is simply to
// be returned
//
// The return value is the size (in bytes) of the transfer data
uint TCoolGrid::TTextCell::Transfer(void* buffer, TTransferDirection direction)
{
if (!buffer && direction != tdSizeData) return 0;
if (direction == tdGetData)
_tcscpy((_TCHAR*)buffer, Text);
else if (direction == tdSetData)
SetText((_TCHAR *)buffer);
return TextLimit;
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TBitmapCell
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TBitmapCell::TBitmapCell(const TResId& resIdorIndex, int numImages,
int startImage, bool sharedCels)
:
ImageArray(0), // Created on first call to GetDesiredSize
CurrentImage(startImage),
NumImages(numImages),
BitmapOrigin(0,0)
{
if(sharedCels) {
ResId = 0;
CHECK(resIdorIndex.IsInt());
ImageIndex = resIdorIndex.GetInt();
}
else {
ResId = resIdorIndex;
ImageIndex = 0;
}
}
//
TCoolGrid::TBitmapCell::~TBitmapCell()
{
delete ImageArray;
}
//
int
TCoolGrid::TBitmapCell::SelectImage(int imageNum, bool immediate)
{
PRECONDITION(Parent);
PRECONDITION(imageNum >=0 && imageNum < NumImages);
uint oldImageNum = CurrentImage;
if (imageNum != CurrentImage) {
CurrentImage = imageNum;
Parent->Invalidate(false);
}
if(immediate)
Parent->UpdateWindow();
return oldImageNum;
}
//
// Handle a system color change by cleaning up & reloading & processing the
// bitmap. Is also called to create the initial bitmap.
//
void
TCoolGrid::TBitmapCell::SysColorChange()
{
PRECONDITION(Parent);
delete ImageArray;
if(ResId){
TDib dib(*Parent->GetModule(), ResId);
dib.MapUIColors(TDib::MapFace | TDib::MapText | TDib::MapShadow |
TDib::MapHighlight);
ImageArray = new TCelArray(dib, NumImages);
}
}
//
void TCoolGrid::TBitmapCell::Paint(TDC& dc, const TRect& rect)
{
PRECONDITION(Parent);
TCelArray& imageArray = ImageArray ? *ImageArray : Parent->GetCelArray();
imageArray.BitBlt(ImageIndex+CurrentImage, dc, rect.left, rect.top);
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TBitmapTextCell
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TBitmapTextCell::TBitmapTextCell(const TResId& resIdorIndex,
int numImages, LPCTSTR text, uint textLimit, int startImage, bool sharedCels)
:
TTextCell(text, textLimit),
ImageArray(0), // Created on first call to GetDesiredSize
CurrentImage(startImage),
NumImages(numImages),
BitmapOrigin(0,0)
{
if(sharedCels) {
ResId = 0;
CHECK(resIdorIndex.IsInt());
ImageIndex = resIdorIndex.GetInt();
}
else {
ResId = resIdorIndex;
ImageIndex = 0;
}
}
//
TCoolGrid::TBitmapTextCell::~TBitmapTextCell()
{
delete ImageArray;
}
//
int
TCoolGrid::TBitmapTextCell::SelectImage(int imageNum, bool immediate)
{
PRECONDITION(Parent);
PRECONDITION(imageNum >=0 && imageNum < NumImages);
uint oldImageNum = CurrentImage;
if (imageNum != CurrentImage) {
CurrentImage = imageNum;
Parent->Invalidate(false);
}
if(immediate)
Parent->UpdateWindow();
return oldImageNum;
}
//
// Handle a system color change by cleaning up & reloading & processing the
// bitmap. Is also called to create the initial bitmap.
//
void
TCoolGrid::TBitmapTextCell::SysColorChange()
{
PRECONDITION(Parent);
delete ImageArray;
if(ResId){
CHECK(NumImages);
TDib dib(*Parent->GetModule(), ResId);
dib.MapUIColors(TDib::MapFace | TDib::MapText | TDib::MapShadow |
TDib::MapHighlight);
ImageArray = new TCelArray(dib, NumImages);
}
}
//
void TCoolGrid::TBitmapTextCell::Paint(TDC& dc, const TRect& rect)
{
PRECONDITION(Parent);
TRect textRect,bmpRect;
Layout(rect,textRect,bmpRect);
TColor oldBgClr = dc.SetBkColor(BgColor);
TColor oldTxClr = dc.SetTextColor(TxColor);
dc.TextRect(rect);
dc.SetBkColor(oldBgClr);
dc.SetTextColor(oldTxClr);
TTextCell::Paint(dc, textRect);
PaintBitmap(dc, bmpRect);
}
//
void TCoolGrid::TBitmapTextCell::Layout(const TRect& src,TRect& txr,TRect& bmpr)
{
PRECONDITION(Parent);
if(NumImages){
TCelArray& imageArray = ImageArray ? *ImageArray : Parent->GetCelArray();
TSize bsize = imageArray.CelSize();
bmpr.top = src.top + (src.Height()-bsize.cy)/2;
bmpr.left = src.left;
bmpr.right = bmpr.left + bsize.cx;
bmpr.bottom = src.bottom;
}
txr.top = src.top;
txr.left = bmpr.right;
txr.right = src.right;
txr.bottom= src.bottom;
}
//
void TCoolGrid::TBitmapTextCell::PaintBitmap(TDC& dc, const TRect& rect)
{
PRECONDITION(Parent);
if(NumImages){
TCelArray& imageArray = ImageArray ? *ImageArray : Parent->GetCelArray();
imageArray.BitBlt(ImageIndex+CurrentImage, dc, rect.left, rect.top);
}
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TButtonCell
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TButtonCell::TButtonCell(const TResId& resIdorIndex,
int numImages, LPCTSTR text, uint textLimit, int startImage, bool sharedCels)
:
TBitmapTextCell(resIdorIndex, numImages,text,textLimit,startImage,sharedCels)
{
SetTxColor(TColor::SysBtnText);
SetBgColor(TColor::Sys3dFace);
}
//
void TCoolGrid::TButtonCell::Paint(TDC& dc, const TRect& rect)
{
Inherited::Paint(dc, rect);
if(TCell::IsSet(cfButtonDown))
TUIBorder(rect, TUIBorder::ButtonDn).Paint(dc);
else
TUIBorder(rect, TUIBorder::ButtonUp).Paint(dc);
}
//
void TCoolGrid::TButtonCell::MouseDown(uint /*modKeys*/, const TPoint&)
{
PRECONDITION(Parent);
if(Parent->CellSetCapture(*this)){
TCell::Set(cfButtonDown);
Parent->Invalidate();
}
}
//
void TCoolGrid::TButtonCell::MouseUp(uint modKeys, const TPoint& point)
{
if(Parent->CellGetCaptured()==this){
TCell::Clear(cfButtonDown);
Parent->CellReleaseCapture(*this);
TCellPos pos = Parent->Point2Pos(point);
Parent->Invalidate();
if(Parent->GetCell(pos) == this)
Action(modKeys, point);
}
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TCommandCell
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TCommandCell::TCommandCell(int id, const TResId& resIdorIndex,
int numImages, LPCTSTR text, uint textLimit, int startImage, bool sharedCels)
:
TButtonCell(resIdorIndex, numImages,text,textLimit,startImage,sharedCels),
Id(id)
{
}
//
void TCoolGrid::TCommandCell::Action(uint /*modKeys*/, const TPoint&)
{
Parent->SendNotification(Parent->GetHandle(), Id, BN_CLICKED,0,WM_COMMAND);
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TEditCell
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TEditCell::TEditCell()
:
InPlaceEdit(0)
{
Set(cfTransfer); // enable transfer
}
//-----------------------------------------------------------------------------
TCoolGrid::TEditCell::TEditCell(LPCTSTR text, uint textLimit)
:
TCoolGrid::TTextCell(text, textLimit),
InPlaceEdit(0)
{
Set(cfTransfer); // enable transfer
}
//-----------------------------------------------------------------------------
TCoolGrid::TEditCell::TEditCell(const owl::tstring& text, uint textLimit)
:
TCoolGrid::TTextCell(text, textLimit),
InPlaceEdit(0)
{
Set(cfTransfer); // enable transfer
}
//-----------------------------------------------------------------------------
TCoolGrid::TEditCell::~TEditCell()
{
delete InPlaceEdit;
}
//
void TCoolGrid::TEditCell::SetInPlaceEdit(TInPlaceEdit* edit)
{
delete InPlaceEdit;
InPlaceEdit = edit;
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::THeaderCell
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
//
//
TCoolGrid::THeaderCell::THeaderCell(LPCTSTR text, uint textLimit)
:
TCoolGrid::TTextCell(text, textLimit)
{
SetBgColor(TColor::Sys3dFace);
}
//
TCoolGrid::THeaderCell::THeaderCell(const owl::tstring& text, uint textLimit)
:
TCoolGrid::TTextCell(text, textLimit)
{
SetBgColor(TColor::Sys3dFace);
}
//
void TCoolGrid::THeaderCell::Paint(TDC& dc, const TRect& rect)
{
PRECONDITION(Parent);
if(!Text){
TTextCell::Paint(dc, rect);
return;
}
// TColor oldBgClr = dc.SetBkColor(BgColor);
// TColor oldTxClr = dc.SetTextColor(TxColor);
TRect r = rect;
dc.DrawTextEx(Text, -1, &r, Format);
// dc.SetBkColor(oldBgClr);
// dc.SetTextColor(oldTxClr);
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TComboBoxCell
// ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TComboBoxCell::TComboBoxCell()
:
InPlaceEdit(0)
{
Set(cfTransfer); // enable transfer
}
//
TCoolGrid::TComboBoxCell::TComboBoxCell(LPCTSTR text, uint textLimit)
:
TTextCell(text, textLimit),
InPlaceEdit(0)
{
Set(cfTransfer); // enable transfer
}
//
TCoolGrid::TComboBoxCell::TComboBoxCell(const owl::tstring& text, uint textLimit)
:
TTextCell(text, textLimit),
InPlaceEdit(0)
{
Set(cfTransfer); // enable transfer
}
//
TCoolGrid::TComboBoxCell::~TComboBoxCell()
{
delete InPlaceEdit;
}
//
void TCoolGrid::TComboBoxCell::SetInPlaceEdit(TInPlaceEdit* edit)
{
delete InPlaceEdit;
InPlaceEdit = edit;
}
//
void TCoolGrid::TComboBoxCell::Paint(TDC& dc, const TRect& rect)
{
TRect btnRect(rect);
if(!IsSet(cfNoShowButton))
btnRect.right -= TUIMetric::CxVScroll;
Inherited::Paint(dc, btnRect);
if(!IsSet(cfNoShowButton)){
btnRect.left = rect.right - btnRect.Height();
btnRect.right = rect.right;
TUIPart().Paint(dc, btnRect, TUIPart::uiScroll,TUIPart::ScrollDown);
}
}
//
uint TCoolGrid::TComboBoxCell::Transfer(void* buffer, TTransferDirection direction)
{
return Inherited::Transfer(buffer, direction);
}
////////////////////////////////////////////////////////////////////
// class TCoolGrid::TColumn
// ~~~~~ ~~~~~~~~~~~~~~~~~~
//
TCoolGrid::TColumn::TColumn(TCoolGrid& parent)
:
Parent(parent),
InPlaceEdit(0),
DefColor(TColor::SysWindow),
Font(0),
BoldFont(0),
CellBuilder(TCell_FUNCTOR(CreateCoolCell)),
Header(0)
{
Set(cfTransfer);
}
//
TCoolGrid::TColumn::~TColumn()
{
delete InPlaceEdit;
delete Font;
delete Header;
}
//
TCoolGrid::TCell*
TCoolGrid::TColumn::operator [](int loc)
{
TCellMap::iterator itr = CellMap.find(loc);
if(itr != CellMap.end())
return (*itr).second;
return 0;
}
//
void TCoolGrid::TColumn::SetInPlaceEdit(TInPlaceEdit* edit)
{
delete InPlaceEdit;
InPlaceEdit = edit;
}
//
void TCoolGrid::TColumn::SetCell(int loc, TCell& cell)
{
cell.SetParent(&Parent);
TCellMap::iterator itr = CellMap.find(loc);
if(itr != CellMap.end()){
delete (*itr).second;
(*itr).second = &cell;
}
else
CellMap.insert(TCellMap::value_type(loc, &cell));
cell.SysColorChange();
}
//
void TCoolGrid::TColumn::RemoveCell(int loc)
{
TCellMap::iterator itr = CellMap.find(loc);
if(itr != CellMap.end()){
delete (*itr).second;
CellMap.erase(itr);
}
}
//
void TCoolGrid::TColumn::SetHeader(const owl::tstring& text)
{
if(Header)
Header->SetText(text.c_str());
else
SetHeader(new THeaderCell(text.c_str()));
}
//
void TCoolGrid::TColumn::SetHeader(THeaderCell* cell)
{
delete Header;
Header = cell;
if(Header){
Header->SetParent(&Parent);
Header->SysColorChange();
}
}
//
void TCoolGrid::TColumn::PaintDefaultHeader(TDC& dc, const TRect& rect)
{
Parent.PaintHorizHeaderCell(dc, rect, Id);
}
//
void TCoolGrid::TColumn::PaintHeader(TDC& dc, const TRect& rect, THeaderCell* cell)
{
PRECONDITION(cell);
TColor oldBgClr = dc.SetBkColor(cell->GetBgColor());
TColor oldTxClr = dc.SetTextColor(cell->GetTxColor());
VERIFY(dc.TextRect(rect));
TUIBorder::TStyle style = TUIBorder::Raised;
TFont* font = GetFont();
const TCellPos& fpos = Parent.GetFocusPos();
if(fpos.Valid() && fpos.col == Id && !Parent.IsRowSelection()){
style = TUIBorder::ButtonUp;
font = GetBoldFont();
}
TUIBorder(rect,style,TUIBorder::Rect|TUIBorder::Soft).Paint(dc);
if(font){
CHECK(font->IsGDIObject());
dc.SelectObject(*font);
}
TRect textRect(rect);
textRect.Inflate(-2,-2);
Header->Paint(dc, textRect);
if(font)
dc.RestoreFont();
dc.SetBkColor(oldBgClr);
dc.SetTextColor(oldTxClr);
}
//
void TCoolGrid::TColumn::Paint(TDC& dc, const TRect& rect)
{
int lastCellId = Parent.GetRowCount()-1;
bool hasHeader = Parent.IsHorizHeader();
int headerDelta = 0;
if(hasHeader)
headerDelta = Parent.GetHeaderHeight() + Parent.GetLineHeight();
TRect colmnRect(rect);
colmnRect.top -= Parent.GetTopPos();
colmnRect.right += Parent.GetLineWidth();
colmnRect.top += headerDelta;
colmnRect.bottom = Parent.Index2Y(lastCellId) +
Parent.GetRowHeight(lastCellId) + headerDelta;
TColor oldClr = dc.SetBkColor(DefColor);
dc.TextRect(colmnRect);
dc.SetBkColor(oldClr);
for(TCellMap::iterator itr = CellMap.begin();
itr != CellMap.end(); itr++){
TRect cellRect(colmnRect);
cellRect.top = Parent.Index2Y((*itr).first) + headerDelta;
cellRect.bottom = cellRect.top + Parent.GetRowHeight((*itr).first);
if(cellRect.top > rect.bottom)
break;
if(cellRect.bottom > headerDelta)
(*itr).second->Paint(dc, cellRect);
}
if(hasHeader){
TRect hdrRect(rect);
hdrRect.bottom = hdrRect.top + headerDelta;
hdrRect.right += Parent.GetLineWidth();
if(Header)
PaintHeader(dc, hdrRect, Header);
else
PaintDefaultHeader(dc, hdrRect);
}
// fill rest area
colmnRect.top = colmnRect.bottom;
colmnRect.bottom = rect.bottom;
oldClr = dc.SetBkColor(TColor::SysAppWorkspace);
dc.TextRect(colmnRect);
dc.SetBkColor(oldClr);
}
//
void
TCoolGrid::TColumn::SetFont(const TFont& font)
{
delete Font;
Font = new TFont(font);
}
//
void
TCoolGrid::TColumn::SetBoldFont(const TFont& font)
{
delete BoldFont;
BoldFont = new TFont(font);
}
//
TCoolGrid::TCell*
TCoolGrid::TColumn::FirstThat(TCellCondOperator& test)
{
for(TCellMap::iterator itr = CellMap.begin(); itr != CellMap.end(); itr++){
if(test((*itr).second))
return (*itr).second;
}
return 0;
}
//
TCoolGrid::TCell*
TCoolGrid::TColumn::LastThat(TCellCondOperator& test)
{
TCell* lastCell = 0;
for(TCellMap::iterator itr = CellMap.begin(); itr != CellMap.end(); itr++){
if(test((*itr).second))
lastCell = (*itr).second;
}
return lastCell;
}
//
void
TCoolGrid::TColumn::ForEach(TCellActionOperator& action)
{
for(TCellMap::iterator itr = CellMap.begin(); itr != CellMap.end(); itr++)
action((*itr).second);
}
//
struct TTransferCellOp: public TCellActionOperator {
TTransferCellOp(void* buff, TTransferDirection dir)
:Data(buff),Direction(dir){}
void operator ()(TCoolGrid::TCell* cell)
{
if(cell->IsSet(TCoolGrid::TCell::cfTransfer))
Data = (char*)Data + cell->Transfer(Data, Direction);
}
void* Data;
TTransferDirection Direction;
};
//
uint TCoolGrid::TColumn::Transfer(void* buffer, TTransferDirection direction)
{
if (!buffer && direction != tdSizeData) return 0;
TTransferCellOp op(buffer, direction);
ForEach(op);
return static_cast<uint>((char*)op.Data - (char*)buffer);
}
//
// struct TColSelection
//
void TCoolGrid::TColSelection::Paint(TDC& dc)
{
TRect rowRect;
rowRect.top = 0;
rowRect.bottom= Parent->Index2Y(Parent->RowCount-1) +
Parent->GetRowHeight(Parent->RowCount-1);
if(Parent->IsFlagSet(TCoolGrid::gfHorizHeader))
rowRect.bottom += Parent->GetHeaderHeight()+Parent->GetLineHeight();
rowRect.left = Parent->Index2X(Column);
if(Parent->IsFlagSet(TCoolGrid::gfVertHeader))
rowRect.left += Parent->GetHeaderWidth()+Parent->GetLineWidth();
rowRect.right = rowRect.left + Parent->GetColumnWidth(Column);
VERIFY(dc.InvertRect(rowRect));
}
//
void TCoolGrid::TColSelection::PaintHHeader(TDC& dc)
{
if(Parent->IsFlagSet(TCoolGrid::gfHorizHeader)){
TRect rowRect;
rowRect.top = 0;
rowRect.bottom= Parent->GetHeaderHeight()+Parent->GetLineHeight();
rowRect.left = Parent->Index2X(Column);
if(Parent->IsFlagSet(TCoolGrid::gfVertHeader))
rowRect.left += Parent->GetHeaderWidth()+Parent->GetLineWidth();
rowRect.right = rowRect.left + Parent->GetColumnWidth(Column);
VERIFY(dc.InvertRect(rowRect));
}
}
//
// struct TRowSelection
//
void TCoolGrid::TRowSelection::Paint(TDC& dc)
{
TRect rowRect;
rowRect.top = Parent->Index2Y(Row);
if(Parent->IsFlagSet(TCoolGrid::gfHorizHeader))
rowRect.top += Parent->GetHeaderHeight()+Parent->GetLineHeight();
rowRect.bottom= rowRect.top + Parent->GetRowHeight(Row);
rowRect.left = 0;
rowRect.right = Parent->Index2X(Parent->GetColCount()-1) +
Parent->GetColumnWidth(Parent->GetColCount()-1);
if(Parent->IsFlagSet(TCoolGrid::gfVertHeader))
rowRect.right += Parent->GetHeaderWidth()+Parent->GetLineWidth();
VERIFY(dc.InvertRect(rowRect));
}
//
void TCoolGrid::TRowSelection::PaintVHeader(TDC& dc)
{
if(Parent->IsFlagSet(TCoolGrid::gfVertHeader)){
TRect rowRect;
rowRect.top = Parent->Index2Y(Row);
if(Parent->IsFlagSet(TCoolGrid::gfHorizHeader))
rowRect.top += Parent->GetHeaderHeight() + Parent->GetLineHeight();
rowRect.bottom = rowRect.top + Parent->GetRowHeight(Row);
rowRect.left = 0;
rowRect.right = Parent->GetHeaderWidth() + Parent->GetLineWidth();
VERIFY(dc.InvertRect(rowRect));
}
}
//
void TCoolGrid::TRandSelection::Paint(TDC&)
{
}
//
void TCoolGrid::TAllSelection::Paint(TDC& dc)
{
TRect rect;
Parent->GetClientRect(rect);
VERIFY(dc.InvertRect(rect)); InUse(dc);
}
//
void TCoolGrid::TAllSelection::PaintHHeader(TDC& dc)
{
if(Parent->IsFlagSet(TCoolGrid::gfHorizHeader)){
TRect rect;
Parent->GetClientRect(rect);
rect.bottom = Parent->GetHeaderHeight()+Parent->GetLineHeight();
VERIFY(dc.InvertRect(rect));
}
}
//
void TCoolGrid::TAllSelection::PaintVHeader(TDC& dc)
{
if(Parent->IsFlagSet(TCoolGrid::gfVertHeader)){
TRect rect;
Parent->GetClientRect(rect);
rect.right = Parent->GetHeaderWidth() + Parent->GetLineWidth();
VERIFY(dc.InvertRect(rect));
}
}
//
TCoolGridScroller::TCoolGridScroller(TWindow* window, int xUnit, int yUnit,
long xRange,long yRange)
:
TScroller(window, xUnit, yUnit, xRange,yRange)
{
}
//-----------------------------------------------------------------------------
// sets the range of the Window's scrollbars & repaints as necessary
//
void
TCoolGridScroller::SetSBarRange()
{
PRECONDITION(Window);
PRECONDITION(Window->GetHandle());
if (Window && Window->GetHandle()) {
if (HasHScrollBar) {
int curMin, curMax;
GetScrollRange(SB_HORZ, curMin, curMax);
int newMax = std::max(0, std::min(int(XRange-1), SHRT_MAX));
if (newMax != curMax || curMin != 0)
SetScrollRange(SB_HORZ, 0, newMax, true);
}
if (HasVScrollBar) {
int curMin, curMax;
GetScrollRange(SB_VERT, curMin, curMax);
int newMax = std::max(0, std::min(int(YRange-1), SHRT_MAX));
if (newMax != curMax || curMin != 0)
SetScrollRange(SB_VERT, 0, newMax, true);
}
}
}
//-----------------------------------------------------------------------------
void TCoolGridScroller::ScrollTo(long x, long y)
{
PRECONDITION(Window);
PRECONDITION(Window->GetHandle());
if (Window && Window->GetHandle()) {
long newXPos = std::max(0L, std::min(x, XRange - XPage));
long newYPos = std::max(0L, std::min(y, YRange - YPage));
if (newXPos != XPos || newYPos != YPos) {
//
// scaling isn't needed here. if condition is met, ScrollWindow()
// will succeed since XPage and YPage are ints
//
// if condition isn't met, ScrollWindow() is called in EndScroll()
// as a result of calling UpdateWindow()
//
// EndScroll() performs the necessary scaling
//
TCoolGrid* wnd = TYPESAFE_DOWNCAST(Window, TCoolGrid);
CHECK(wnd);
if (AutoOrg || (abs(YPos-newYPos) < YPage && abs(XPos-newXPos) < XPage)){
TRect clientRect;
Window->GetClientRect(clientRect);
if((YPos - newYPos) == 0)
clientRect.left += wnd->GetHeaderWidth() + wnd->GetLineWidth();
if((XPos - newXPos) == 0)
clientRect.top += wnd->GetHeaderHeight() + wnd->GetLineHeight();
Window->ScrollWindow((int)(XPos - newXPos) * XUnit,
(int)(YPos - newYPos) * YUnit, &clientRect, &clientRect);
}
else
wnd->Invalidate();
XPos = newXPos;
YPos = newYPos;
Window->UpdateWindow();
}
}
}
//
//{{TCoolGrid Implementation}}
//
// Build a response table for all messages/commands handled
// by the application.
//
DEFINE_RESPONSE_TABLE1(TCoolGrid, TControl)
EV_WM_LBUTTONDOWN,
EV_WM_SIZE,
EV_WM_LBUTTONDBLCLK,
EV_WM_KEYDOWN,
EV_MESSAGE(COOLGRID_ENDEDIT, EvEndEdit),
EV_WM_CHAR,
EV_WM_SETCURSOR,
EV_WM_MOUSEMOVE,
EV_WM_LBUTTONUP,
EV_WM_SYSCOLORCHANGE,
END_RESPONSE_TABLE;
int TCoolGrid::DefaultWidth = 50;
int TCoolGrid::DefaultHeight = -1;
//--------------------------------------------------------
// TCoolGrid Constructor
//
TCoolGrid::TCoolGrid(TWindow* parent,int id,LPCTSTR title,int x, int y, int w, int h,TModule* module)
:
TControl(parent,id,title,x,y,w,h,module),
Flags(gfBothHeaders|gfResHHeader),
MemBitmap(0),
Font(0),
BoldFont(0),
DefColor(TColor::SysWindow),
Width(DefaultWidth),
Height(DefaultHeight),
ColCount(0),
RowCount(0),
CharSize(-1,-1),
HeaderWidth(DefaultWidth),
HeaderHeight(DefaultHeight),
DefVertFormat(_T("%d")),
DefHorFormat(_T("%d")),
LineWidth(1),
LineHeight(1),
FocusedCell(-1,-1),
Capture(0),
InPlaceEdit(0),
CurrentEdit(0),
ColBuilder(TColumn_FUNCTOR(CreateCoolColumn)),
CellBuilder(TCell_FUNCTOR(CreateCoolCell)),
Selection(0),
SharedCels(0)
{
SetBkgndColor(TColor::Transparent);
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
LOGFONT lfFont = ncm.lfSmCaptionFont;
lfFont.lfWeight = FW_NORMAL;
Font = new TFont(lfFont);
lfFont.lfWeight = FW_BOLD;
BoldFont = new TFont(lfFont);
}
//--------------------------------------------------------
// TCoolGrid Destructor
//
TCoolGrid::~TCoolGrid()
{
delete Selection;
delete MemBitmap;
delete InPlaceEdit;
delete Font;
delete BoldFont;
delete SharedCels;
Destroy(IDCANCEL);
}
//
auto TCoolGrid::GetWindowClassName() -> TWindowClassName
{
return TWindowClassName{_T("CoolGrid")};
}
//
void TCoolGrid::GetWindowClass(WNDCLASS& wndClass)
{
// Call base class function.
TControl::GetWindowClass(wndClass);
wndClass.style |= CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
}
//
int TCoolGrid::FindMaxColWidth() const
{
int width = Width;
for(TDimMap::const_iterator itr = WidthMap.begin(); itr != WidthMap.end(); itr++)
width = std::max(width, (*itr).second);
return width;
}
//
void TCoolGrid::SetCelArray(TCelArray* sharedCels)
{
delete SharedCels;
SharedCels = sharedCels;
}
//
TCelArray& TCoolGrid::GetCelArray(int minX, int minY)
{
if (!SharedCels) {
//!CQ default??? BOGUS values here for now on purpose
if(!minX)
minX = 10;
if(!minY)
minY = 10;
SharedCels = new TCelArray(TSize(minX,minY), 0, 10, 5);
}
return *SharedCels;
}
//
void TCoolGrid::Paint(TDC& dc, bool /*erase*/, TRect& /*rect*/)
{
TRect clientRect;
GetClientRect(clientRect);
TRect columnRect(clientRect.TopLeft(), TSize(FindMaxColWidth(), clientRect.Height()));
// must be member variables
TMemoryDC memDC(dc);
if(!MemBitmap)
MemBitmap = new TBitmap(dc, columnRect.Width()+GetLineWidth(),
columnRect.Height()+GetLineHeight());
memDC.SelectObject(*MemBitmap);
int deltaWidth = HeaderWidth + LineWidth;
TRect workRect(columnRect);
workRect.right += LineWidth;
workRect.bottom += LineHeight;
if(IsFlagSet(gfVertHeader)){
workRect.right = workRect.left + deltaWidth;
PaintHeaderColumn(memDC, workRect);
// paint corner
if(IsFlagSet(gfHorizHeader)){
TRect cellRect(columnRect);
cellRect.bottom = cellRect.top + HeaderHeight + LineHeight;
cellRect.right = cellRect.left + deltaWidth;
PaintCornerCell(memDC, cellRect);
}
VERIFY(dc.BitBlt(workRect, memDC, TPoint(0,0)));
workRect.Offset(deltaWidth, 0);
}
//
// Paint Vertical headre selections and
// exclude vertical header area from paint
//
if(IsVertHeader()){
// Paint Vertical Borders for Focused Cell
if(Selection)
Selection->PaintVHeader(dc);
else if(FocusedCell.Valid()){
// paint on DC, not on MemDC, why, maby better would be on MemDC ???
if(IsFlagSet(gfRowSelect)){
// paint full row
TRect rowRect;
rowRect.top = Index2Y(FocusedCell.row);
if(IsHorizHeader())
rowRect.top += HeaderHeight+LineHeight;
rowRect.bottom = rowRect.top + GetRowHeight(FocusedCell.row);
rowRect.left = 0;
rowRect.right = HeaderWidth+LineWidth;
if(IsFlagSet(gfNoRowInvert)){
rowRect.Inflate(1,1);
rowRect.right +=2;// will be erased
TUIBorder(rowRect, TUIBorder::ButtonDn, TUIBorder::Rect|TUIBorder::Soft).Paint(dc);
}
else{
VERIFY(dc.InvertRect(rowRect));
}
}
}
// exclude horisontal headrs from painting
#ifndef _MSC_VER // VC fail to compile this code
TRect clipRect(columnRect);
clipRect.right = clipRect.left + deltaWidth;
dc.ExcludeClipRect(clipRect);
#else
int oldright = columnRect.right;
columnRect.right = columnRect.left + deltaWidth;
dc.ExcludeClipRect(columnRect);
columnRect.right = oldright;
#endif
}
//
// Draw all columns
//
workRect.Offset(-GetOffsetPos(), 0);
int i = FirstVisibleColumn();
for(; i < ColCount && workRect.left < clientRect.right; i++){
// calculate rectangle
TDimMap::iterator itr1 = WidthMap.find(i);
int col_with = itr1 != WidthMap.end() ? (*itr1).second : Width;
columnRect.right = columnRect.left+col_with;
TColumnMap::iterator itr = ColumnMap.find(i);
if(itr != ColumnMap.end())
(*itr).second->Paint(memDC, columnRect);
else
PaintDefaultColumn(memDC, columnRect, i);
// Paint this Column Grid
PaintGridLines(memDC, columnRect);
workRect.right = workRect.left + col_with + LineWidth;
VERIFY(dc.BitBlt(workRect, memDC, TPoint(0,0)));
workRect.Offset(col_with+GetLineWidth(), 0);
}
workRect.Offset(GetOffsetPos(), 0);
//
// Restore original bitmap before leaving
//
memDC.RestoreBitmap();
// fill rest area
if(workRect.left < clientRect.right){
workRect.right = clientRect.right + LineWidth - GetOffsetPos();
TColor oldClr = dc.SetBkColor(TColor::SysAppWorkspace);
VERIFY(dc.TextRect(workRect));
dc.SetBkColor(oldClr);
}
//
// Paint Vertical headre selections and
// exclude Horisontal header area from paint
//
if(IsFlagSet(gfHorizHeader)){
// Paint Vertical Borders for Focused Cell
if(Selection)
Selection->PaintHHeader(dc);
TRect clipRect(clientRect);
clipRect.bottom = clipRect.top + HeaderHeight + LineHeight;
dc.ExcludeClipRect(clipRect);
}
// Paint Rest of Focused Cell
if(Selection)
Selection->Paint(dc);
else if(FocusedCell.Valid()){
TRect cellRect;
GetCellRect(FocusedCell, cellRect);
PaintFocusedCell(dc, cellRect);
}
}
//
void TCoolGrid::Cell2EditTransfer(TCell& cell, TInPlaceEdit& edit)
{
uint size = cell.Transfer(0, tdSizeData);
if(size){
TAPointer<uint8> buffer(new uint8[size]);
cell.Transfer((void*)(uint8*)buffer, tdGetData);
edit.Transfer((void*)(uint8*)buffer, tdSetData);
}
}
//
void TCoolGrid::Edit2CellTransfer(TInPlaceEdit& edit, TCell& cell)
{
// transfer data to/from edit
uint size = edit.Transfer(0, tdSizeData);
if(size){
TAPointer<uint8> buffer(new uint8[size]);
edit.Transfer((void*)(uint8*)buffer, tdGetData);
cell.Transfer((void*)(uint8*)buffer, tdSetData);
}
}
//
TResult TCoolGrid::EvEndEdit(TParam1, TParam2)
{
SetFocus();
if(CurrentEdit){
TCell* cell = GetFocusedCell();
if(cell)
Cell2EditTransfer(*cell, *CurrentEdit);
TRect rect;
GetCellRect(FocusedCell, rect);
InvalidateRect(rect);
uint lastKey = CurrentEdit->GetLastKey();
CurrentEdit = 0;
switch (lastKey){
case VK_TAB: case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT:
case VK_NEXT: case VK_PRIOR: case VK_HOME: case VK_END:
EvKeyDown(lastKey, 1, 0);
//OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, pgvItem->lParam);
}
}
return 0;
}
//
void TCoolGrid::PaintVDivider(const TPoint& point, bool redraw)
{
TRect rect;
GetClientRect(rect);
TClientDC dc(GetHandle());
if(redraw){
rect.top = LastDrawPoint.y;
rect.bottom = LastDrawPoint.y+2;
dc.InvertRect(rect);
}
int pos_y = point.y;
if(MinDividerIndex==-1){
if(pos_y < HitDelta*2)
pos_y = HitDelta*2;
}
else {
int minPos = Index2Y(MinDividerIndex)+HitDelta*2;
minPos += IsHorizHeader() ? (HeaderHeight+LineHeight) : 0;
if(pos_y < minPos)
pos_y = minPos;
}
rect.top = pos_y;
rect.bottom = pos_y+2;
dc.InvertRect(rect);
LastDrawPoint = TPoint(LastDrawPoint.x, pos_y);
}
//
void TCoolGrid::PaintHDivider(const TPoint& point, bool redraw)
{
TRect rect;
GetClientRect(rect);
TClientDC dc(GetHandle());
if(redraw){
rect.left = LastDrawPoint.x;
rect.right = LastDrawPoint.x + 2;
dc.InvertRect(rect);
}
int pos_x = point.x;
if(MinDividerIndex==-1){
if(pos_x < HitDelta*4)
pos_x = HitDelta*4;
}
else {
int minPos = Index2X(MinDividerIndex)+HitDelta*4;
minPos += IsVertHeader() ? (HeaderWidth+LineWidth) : 0;
if(pos_x < minPos)
pos_x = minPos;
}
rect.left = pos_x;
rect.right = pos_x+2;
dc.InvertRect(rect);
LastDrawPoint = TPoint(pos_x, LastDrawPoint.y);
}
//
void TCoolGrid::ResizeColumn(int column, int delta)
{
if(column==-1)
SetHeaderWidth(GetHeaderWidth()+delta);
else
SetColumnWidth(column, GetColumnWidth(column)+delta);
delete MemBitmap;
MemBitmap = 0;
Invalidate();
}
//
void TCoolGrid::ResizeRow(int row, int delta)
{
if(row==-1)
SetHeaderHeight(GetHeaderHeight()+delta);
else
SetRowHeight(row, GetRowHeight(row)+delta);
Invalidate();
}
//
void TCoolGrid::CleanupSelection()
{
if(Selection){
delete Selection;
Selection = 0;
Invalidate();
UpdateWindow();
}
}
//
void TCoolGrid::EvLButtonDown(uint modKeys, const TPoint& point)
{
SetFocus(); // destroy any InplaysEdits
CleanupSelection();
MouseDownPoint = point;
THitResult hitRes = hrGridBody;
if(IsFlagSet(gfBothHeaders))
hitRes = HitTest(point);
if(hitRes!=hrGridBody){
if(hitRes==hrVHeader){
if(IsFlagSet(gfRowSelect)){
// if Set new row
SetFocusCell(TCellPos(FocusedCell.col,Y2Index(point.y)));
}
else{
SetFocusCell(TCellPos(-1,Y2Index(point.y)));
Selection = new TRowSelection(this, Y2Index(point.y));
Invalidate();
}
}
else if(hitRes==hrBothHds && !IsFlagSet(gfRowSelect)){
SetFocusCell(TCellPos());
Selection = new TAllSelection(this);
Invalidate();
}
else if(hitRes==hrHHeader && !IsFlagSet(gfRowSelect)){
SetFocusCell(TCellPos(X2Index(point.x),-1));
Selection = new TColSelection(this, X2Index(point.x));
Invalidate();
}
else if(hitRes==hrVHDivider && IsFlagSet(gfResVHeader)){
MinDividerIndex = Y2Index(point.y-HitDelta);
PaintVDivider(point);
SetFlag(gfInVResize);
}
else if(hitRes==hrHHDivider && IsFlagSet(gfResHHeader)){
MinDividerIndex = X2Index(point.x-HitDelta);
PaintHDivider(point);
SetFlag(gfInHResize);
}
}
else{
TCellPos pos = Point2Pos(point);
if(pos.Valid()){
SelectionStart = (modKeys & MK_SHIFT) ? FocusedCell : pos;
if(pos==FocusedCell) // maby edit if in Up will be the same
SetFlag(gfMabyEdit);
SetFocusCell(pos);
TCell* cell = GetFocusedCell();
if(cell)
cell->MouseDown(modKeys, point);
}
}
Inherited::EvLButtonDown(modKeys, point);
}
//
void TCoolGrid::EvLButtonDblClk(uint modKeys, const TPoint& point)
{
Inherited::EvLButtonDblClk(modKeys, point);
TCellPos pos = Point2Pos(point);
if(pos.Valid()){
SetFocusCell(pos);
ShowInplaceEdit(VK_LBUTTON);
}
ClearFlag(gfMabyEdit);
}
//
void TCoolGrid::EvMouseMove(uint modKeys, const TPoint& point)
{
if(Capture)
Capture->MouseMove(modKeys, point);
else{
if(IsFlagSet(gfInVResize)||IsFlagSet(gfInHResize)){
if(IsFlagSet(gfInVResize))
PaintVDivider(point, true);
else
PaintHDivider(point, true);
}
}
Inherited::EvMouseMove(modKeys, point);
}
//
void TCoolGrid::EvLButtonUp(uint modKeys, const TPoint& point)
{
Inherited::EvLButtonUp(modKeys, point);
if(IsFlagSet(gfMabyEdit) && Point2Pos(point)==FocusedCell)
ShowInplaceEdit(VK_LBUTTON);
else if(IsFlagSet(gfInVResize)||IsFlagSet(gfInHResize)){
if(IsFlagSet(gfInVResize)){
PaintVDivider(point, true);
PaintVDivider(LastDrawPoint);
ClearFlag(gfInVResize);
if(LastDrawPoint.y != MouseDownPoint.y)
ResizeRow(Y2Index(MouseDownPoint.y-HitDelta),LastDrawPoint.y-MouseDownPoint.y);
}
else{
PaintHDivider(point, true);
PaintHDivider(LastDrawPoint);
ClearFlag(gfInHResize);
if(LastDrawPoint.x != MouseDownPoint.x)
ResizeColumn(X2Index(MouseDownPoint.x-HitDelta), LastDrawPoint.x-MouseDownPoint.x);
}
}
ClearFlag(gfMabyEdit);
if(Capture)
Capture->MouseUp(modKeys, point);
}
//
void TCoolGrid::ShowInplaceEdit(uint key)
{
TCell* cell = GetFocusedCell();
// create new cell if possible
if(!cell){
TColumn* col = GetColumn(FocusedCell.col);
if(!col){
col = (ColBuilder)(*this, FocusedCell.col);
CHECK(col);
cell = col->GetCellBuilder()(*this, FocusedCell);
if(cell){
SetColumn(FocusedCell.col, *col);
col->SetCell(FocusedCell.row, *cell);
}
else
delete col;
}
if(!cell){
cell = CellBuilder(*this, FocusedCell);
if(cell)
SetCell(FocusedCell, *cell);
}
}
if(cell){
// find InPlaceEdit
CurrentEdit = cell->GetInPlaceEdit();
if(!CurrentEdit)
CurrentEdit = GetColumnEdit(FocusedCell.col);
if(!CurrentEdit)
CurrentEdit = GetInPlaceEdit();
// If found show it
if(CurrentEdit){
TRect rect;
GetCellRect(FocusedCell, rect);
// transfer data to/from edit
Cell2EditTransfer(*cell, *CurrentEdit);
CurrentEdit->Activate(rect, key);
}
}
}
//
void TCoolGrid::SetupWindow()
{
// Call base class function.
Inherited::SetupWindow();
if(!Scroller)
//Scroller = new TScroller(this, 7, 16, 80, 60);
Scroller = new TCoolGridScroller(this, 7, 16, 80, 60);
#if !defined(USE_AUTOORG)
Scroller->AutoOrg = false;
#endif
// Set height
TClientDC clientDC(*this);
if(GetFont())
CharSize = GetFont()->GetTextExtent(clientDC, _T("X"));
else
CharSize = clientDC.GetTextExtentPoint32(_T("X"));
CharSize.cy += 4;
if(Height < 0)
Height = CharSize.cy;
if(HeaderHeight < 0)
HeaderHeight = CharSize.cy;
AdjustScroller();
}
//
void TCoolGrid::AdjustScroller()
{
static bool in_work = false;
if(!Scroller || in_work)
return;
in_work = true;
TRect clientRect;
GetClientRect(clientRect);
// Only show scrollbars when image is larger than
// the client area and we are not stretching to fit.
int lastRowId = GetRowCount()-1;
int lastColId = GetColCount()-1;
int headerHDelta = 0;
int headerVDelta = 0;
if(IsHorizHeader())
headerHDelta = GetHeaderHeight() + GetLineHeight();
if(IsVertHeader())
headerVDelta = GetHeaderWidth() + GetLineWidth();
int bottom=Index2Y(lastRowId)+GetTopPos()+GetRowHeight(lastRowId)+GetLineHeight()+headerHDelta;
int right=Index2X(lastColId)+GetOffsetPos()+GetColumnWidth(lastColId)+GetLineWidth()+headerVDelta;
Scroller->SetUnits(1, 1);
//TPoint range(std::max(right - clientRect.Width(), 0), std::max(bottom - clientRect.Height(), 0));
TPoint range(std::max(right, 0), std::max(bottom, 0));
Scroller->SetRange(range.x, range.y);
// Scroller->XLine = 10; // # of horz/vert scroll units per line
// Scroller->YLine = 10; //
// Scroller->XPage = clientRect.Width()*2/3; // # of horz/vert scroll units per page
// Scroller->YPage = clientRect.Height()*2/3; //
//Scroller->ScrollTo(0, 0);
if (!GetUpdateRect(clientRect, false))
Invalidate(false);
in_work = false;
}
//
void TCoolGrid::EvSize(uint sizeType, const TSize& size)
{
// static bool inScroller = false;
// if(!inScroller){
// inScroller = true;
SetFocus(); // Auto-destroy any InPlaceEdit's
Inherited::EvSize(sizeType, size);
if (sizeType != SIZEICONIC){
delete MemBitmap;
MemBitmap = 0;
// AdjustScroller();
// Invalidate(true);
}
// inScroller = false;
// }
//else
// Inherited::EvSize(sizeType, size);
}
//
void TCoolGrid::EvKeyDown(uint key, uint /*repeatCount*/, uint /*flags*/)
{
bool is_shift = ::GetAsyncKeyState(VK_SHIFT) & MSB;
bool is_ctrl = ::GetAsyncKeyState(VK_CONTROL) & MSB;
switch (key){
//case VK_ESCAPE:
// KeyEscape(repeatCount);
// break;
case VK_TAB:
if(!FocusedCell.Valid())
SetFocusCell(TCellPos(0,0));
else{
TCellPos pos(FocusedCell.col+1, FocusedCell.row);
if(is_shift)
pos.col = FocusedCell.col-1;
if(FocusedCell != pos && pos.col >=0 && pos.col < ColCount)
SetFocusCell(pos);
}
break;
case VK_BACK:
//if(FocusedCell.Valid()&& FocusedCell.col-1 >= 0){
// TCellPos pos(FocusedCell.col);
// pos.col--;
// SetFocusCell(pos);
//}
break;
case VK_RIGHT:
if(!IsFlagSet(gfRowSelect)){
if(!FocusedCell.Valid())
SetFocusCell(TCellPos(0,0));
else if(FocusedCell.col+1 < ColCount){
TCellPos pos(FocusedCell);
pos.col++;
if(is_ctrl)
pos.col = ColCount - 1;
SetFocusCell(pos);
}
break;
} // if Row select -> right the same as down
case VK_DOWN:
if(!FocusedCell.Valid())
SetFocusCell(TCellPos(0,0));
else if(FocusedCell.row+1 < RowCount){
TCellPos pos(FocusedCell);
pos.row++;
if(is_ctrl)
pos.row = RowCount - 1;
SetFocusCell(pos);
}
break;
case VK_LEFT:
if(!IsFlagSet(gfRowSelect)){
if(!FocusedCell.Valid())
SetFocusCell(TCellPos(0,0));
else if(FocusedCell.col-1 >= 0){
TCellPos pos(FocusedCell);
pos.col--;
if(is_ctrl)
pos.col = 0;
SetFocusCell(pos);
}
break;
}
case VK_UP:
if(!FocusedCell.Valid())
SetFocusCell(TCellPos(0,0));
if(FocusedCell.row-1 >= 0){
TCellPos pos(FocusedCell);
pos.row--;
if(is_ctrl)
pos.row = 0;
SetFocusCell(pos);
}
break;
case VK_NEXT: //Page Down
break;
case VK_PRIOR://Page up
break;
case VK_HOME:
if(!FocusedCell.Valid())
SetFocusCell(TCellPos(0,0));
else{
TCellPos pos(0,FocusedCell.row);
if(is_ctrl)
pos.row = 0;
if(FocusedCell != pos)
SetFocusCell(pos);
}
break;
case VK_END:
if(FocusedCell.Valid()){
TCellPos pos(ColCount-1, FocusedCell.row);
if(is_ctrl)
pos.row = RowCount-1;
if(FocusedCell != pos)
SetFocusCell(pos);
}
break;
case VK_INSERT:
break;
case VK_DELETE:
break;
//Anything else is a character key - let windows have it
//back and we will catch it in EvChar.
default:
DefaultProcessing();
return; //NOTE - return not break!
}
//
//Inherited::EvKeyDown(key, repeatCount, flags);//?????????????????????????????????
// INSERT>> Your code here.
}
//
void TCoolGrid::EvChar(uint key, uint repeatCount, uint flags)
{
if( (key != VK_RETURN && key <= VK_ESCAPE) || key == VK_TAB){
Inherited::EvChar(key, repeatCount, flags);
return;
}
bool is_ctrl = ::GetAsyncKeyState(VK_CONTROL) & MSB;
if(!is_ctrl)
ShowInplaceEdit(key);
else
Inherited::EvChar(key, repeatCount, flags);
}
//
bool TCoolGrid::EvSetCursor(HWND hWndCursor, uint hitTest, uint mouseMsg)
{
if (hitTest == HTCLIENT && (IsFlagSet(gfResVHeader)||IsFlagSet(gfResHHeader))){
TPoint point;
GetCursorPos(point);
ScreenToClient(point);
THitResult hitRes = HitTest(point);
if(hitRes == hrVHDivider && IsFlagSet(gfResVHeader)){
::SetCursor(::LoadCursor(0, TResId(IDC_SIZENS)));
return true;
}
else if(hitRes == hrHHDivider && IsFlagSet(gfResHHeader)){
::SetCursor(::LoadCursor(0, TResId(IDC_SIZEWE)));
return true;
}
}
return Inherited::EvSetCursor(hWndCursor, hitTest, mouseMsg);
}
//
TCoolGrid::THitResult
TCoolGrid::HitTest(const TPoint& point)
{
TRect clientRect;
GetClientRect(clientRect);
if(clientRect.Contains(point)){
if(IsVertHeader()||IsHorizHeader()){
if(IsVertHeader()){
if(point.x < (HeaderWidth-HitDelta)){
if(IsHorizHeader()){
if(point.y < (HeaderHeight-HitDelta))
return hrBothHds;
else if(point.y >= (HeaderHeight-HitDelta) && point.y < (HeaderHeight+HitDelta))
return hrVHDivider;
}
int index = Y2Index(point.y-HitDelta);
int pos_y = Index2Y(index) + GetRowHeight(index);
pos_y += IsHorizHeader() ? (HeaderHeight+LineHeight) : 0;
if(point.y >= (pos_y-HitDelta) && point.y < (pos_y+HitDelta))
return hrVHDivider;
return hrVHeader;
}
}
if(IsHorizHeader() && point.y < (HeaderHeight-HitDelta)){
if(IsVertHeader()){
if(point.x >= (HeaderWidth-HitDelta) && point.x < (HeaderWidth+HitDelta))
return hrHHDivider;
}
int index = X2Index(point.x-HitDelta);
int pos_x = Index2X(index) + GetColumnWidth(index);
pos_x += IsVertHeader() ? (HeaderWidth+LineWidth) : 0;
if(point.x > (pos_x-HitDelta) && point.x < (pos_x+HitDelta))
return hrHHDivider;
return hrHHeader;
}
}
return hrGridBody;
}
return hrNone;
}
//
void TCoolGrid::SetResetFlag(uint flag, bool status, bool redraw)
{
if(IsFlagSet(flag) != status){
status ? SetFlag(flag) : ClearFlag(flag);
if(redraw && GetHandle())
Invalidate();
}
}
//
void TCoolGrid::EnableSelection(bool enable)
{
if(IsFlagSet(gfSelectable) != enable){
enable ? SetFlag(gfSelectable) : ClearFlag(gfSelectable);
CleanupSelection();
if(GetHandle())
Invalidate();
}
}
//
void TCoolGrid::EnableRowInvert(bool enable)
{
if(IsFlagSet(gfNoRowInvert) == enable){
enable ? ClearFlag(gfNoRowInvert) : SetFlag(gfNoRowInvert);
if(GetHandle())
Invalidate();
}
}
//
void TCoolGrid::SetColumn(uint loc, TColumn& col)
{
col.Id = loc;
TColumnMap::iterator itr = ColumnMap.find(loc);
if(itr != ColumnMap.end()){
delete (*itr).second;
(*itr).second = &col;
}
else
ColumnMap[loc] = &col;
if(GetHandle()){
AdjustScroller();
Invalidate();
}
}
//
void TCoolGrid::SetGridDim(uint cols, uint rows, int col_width, int row_width)
{
ColCount = cols;
RowCount = rows;
Width = col_width < 0 ? Width : col_width;
Height = row_width < 0 ? Height : row_width;
if(GetHandle()){
AdjustScroller();
Invalidate();
}
}
//
void TCoolGrid::SetRowHeight(uint loc, uint height)
{
TDimMap::iterator itr = HeightMap.find(loc);
if(itr != HeightMap.end())
(*itr).second = height;
else
HeightMap[loc] = height;
if(GetHandle()){
AdjustScroller();
Invalidate();
}
}
//
uint TCoolGrid::GetRowHeight(uint loc) const
{
TDimMap::const_iterator itr = HeightMap.find(loc);
if(itr != HeightMap.end())
return (*itr).second;
else
return Height;
}
//
void TCoolGrid::SetHeaderHeight(int height)
{
HeaderHeight = height;
if(GetHandle()){
AdjustScroller();
Invalidate();
}
}
//
void TCoolGrid::SetHeaderWidth(int width)
{
HeaderWidth = width;
if(GetHandle()){
AdjustScroller();
Invalidate();
}
}
//
void TCoolGrid::SetColumnWidth(uint loc, uint width)
{
TDimMap::iterator itr = WidthMap.find(loc);
if(itr != WidthMap.end())
(*itr).second = width;
else
WidthMap[loc] = width;
if(GetHandle()){
AdjustScroller();
Invalidate();
}
}
//
uint TCoolGrid::GetColumnWidth(uint loc) const
{
TDimMap::const_iterator itr = WidthMap.find(loc);
if(itr != WidthMap.end())
return (*itr).second;
else
return Width;
}
//
void TCoolGrid::InvalidateHeaders(const TRect& rect)
{
if(IsFlagSet(gfVertHeader)){
TRect vrect(rect);
vrect.left = 0;
vrect.right = HeaderWidth+LineWidth;
InvalidateRect(vrect);
}
if(IsFlagSet(gfHorizHeader)){
TRect hrect(rect);
hrect.top = 0;
hrect.bottom = HeaderHeight+LineHeight;
InvalidateRect(hrect);
}
}
//
void TCoolGrid::InvalidateCell(const TCellPos& pos)
{
if(pos.Valid()){
TRect rect;
if(IsFlagSet(gfRowSelect)){
rect.top = Index2Y(pos.row);
if(IsHorizHeader())
rect.top += HeaderHeight+LineHeight;
rect.bottom = rect.top + GetRowHeight(pos.row);
rect.left = 0;
rect.right = Index2X(ColCount-1)+GetColumnWidth(ColCount-1);
if(IsFlagSet(gfVertHeader))
rect.right += HeaderWidth+LineWidth;
}
else{
GetCellRect(pos, rect);
InvalidateHeaders(rect);
}
InvalidateRect(rect.Inflate(4,4));
}
}
//
bool TCoolGrid::SetFocusCell(const TCellPos& pos)
{
if(pos==FocusedCell)
return false;
bool dirty = false;
TCell* cell = GetFocusedCell();
if(cell){
dirty = true;
cell->Clear(TCell::cfFocused);
}
// if(IsFlagSet(gfRowSelect)){
// if(FocusedCell.row!=pos.row)
// InvalidateCell(FocusedCell);
// }else
InvalidateCell(FocusedCell);
FocusedCell = pos;
cell = GetFocusedCell();
if(cell){
dirty = true;
cell->Set(TCell::cfFocused);
}
// if(IsFlagSet(gfRowSelect)){
// if(FocusedCell.row!=pos.row)
// InvalidateCell(FocusedCell);
// }else
InvalidateCell(FocusedCell);
return dirty;
}
//
TCoolGrid::TCell*
TCoolGrid::GetCell(const TCellPos& pos)
{
if(pos.col >= 0 && pos.col < ColCount){
if(pos.row >= 0 && pos.row < RowCount){
TColumnMap::iterator itr = ColumnMap.find(pos.col);
if(itr != ColumnMap.end()){
TCellMap::iterator citr = (*itr).second->CellMap.find(pos.row);
if(citr != (*itr).second->CellMap.end())
return (*citr).second;
}
}
}
return 0;
}
//
int TCoolGrid::X2Index(int point_x) const
{
int width = 0;
if(IsVertHeader())
width += HeaderWidth+LineWidth;
if(point_x < width)
return -1;
point_x += GetOffsetPos();
int last_index = 0;
for(TDimMap::const_iterator itr = WidthMap.begin(); itr != WidthMap.end(); itr++){
if((*itr).first > last_index){
int width_d = Width + LineWidth;
if((width + ((*itr).first-last_index)*width_d) > point_x)
return last_index + (point_x - width)/width_d;
width += ((*itr).first-last_index)*width_d;
last_index = (*itr).first;
}
width += (*itr).second+LineWidth;
if(width > point_x)
return last_index;
last_index++;
}
last_index += (point_x - width)/(Width+LineWidth);
return last_index >= ColCount ? -1 : last_index;
}
//
int TCoolGrid::Y2Index(int point_y) const
{
int height = 0;
if(IsHorizHeader())
height += HeaderHeight + LineHeight;
if(point_y < height)
return -1;
point_y += GetTopPos();
int last_index = 0;
for(TDimMap::const_iterator itr = HeightMap.begin(); itr != HeightMap.end(); itr++){
if((*itr).first > last_index){
int height_d = Height + LineHeight;
if((height + ((*itr).first-last_index)*height_d) > point_y)
return last_index + (point_y - height)/height_d;
height += ((*itr).first-last_index)*height_d;
last_index = (*itr).first;
}
height += (*itr).second + LineHeight;
if(height > point_y)
return last_index;
last_index++;
}
last_index += (point_y - height)/(Height + LineHeight);
return last_index >= RowCount ? -1 : last_index;
}
//
int TCoolGrid::Index2X(int pos_x) const
{
if(pos_x >= ColCount)
return 0;
int width = 0;
int x_count = pos_x;
for(TDimMap::const_iterator itr = WidthMap.begin(); itr != WidthMap.end(); itr++){
if((*itr).first >= pos_x)
break;
width += (*itr).second+LineWidth;
x_count--;
}
if(x_count > 0)
width += x_count*(Width+LineWidth);
return width-GetOffsetPos();
}
//
int TCoolGrid::Index2Y(int pos_y) const
{
if(pos_y >= RowCount)
return 0;
int height = 0;
int y_count = pos_y;
for(TDimMap::const_iterator itr = HeightMap.begin(); itr != HeightMap.end(); itr++){
if((*itr).first >= pos_y)
break;
height += (*itr).second+LineHeight;
y_count--;
}
if(y_count > 0)
height += y_count*(Height+LineHeight);
return height-GetTopPos();
}
//
TCellPos
TCoolGrid::Point2Pos(const TPoint& point) const
{
return TCellPos(X2Index(point.x), Y2Index(point.y));
}
//
struct TTransferColOp: public TColActionOperator{
TTransferColOp(void* buff, TTransferDirection dir)
:Data(buff),Direction(dir){}
void operator ()(TCoolGrid::TColumn* col)
{
if(col->IsSet(TCoolGrid::TColumn::cfTransfer))
Data = (char*)Data + col->Transfer(Data, Direction);
}
void* Data;
TTransferDirection Direction;
};
//
uint TCoolGrid::Transfer(void* buffer, TTransferDirection direction)
{
if (!buffer && direction != tdSizeData) return 0;
TTransferColOp op(buffer, direction);
ForEach(op);
return static_cast<int>((char*)op.Data - (char*)buffer);
}
//
TCoolGrid::TColumn*
TCoolGrid::FirstThat(TColCondOperator& test)
{
for(TColumnMap::iterator itr = ColumnMap.begin(); itr != ColumnMap.end(); itr++)
if(test((*itr).second))
return (*itr).second;
return 0;
}
//
TCoolGrid::TColumn*
TCoolGrid::LastThat(TColCondOperator& test)
{
TColumn* lastColumn = 0;
for(TColumnMap::iterator itr = ColumnMap.begin(); itr != ColumnMap.end(); itr++){
if(test((*itr).second))
lastColumn = (*itr).second;
}
return lastColumn;
}
//
void TCoolGrid::ForEach(TColActionOperator& action)
{
for(TColumnMap::iterator itr = ColumnMap.begin(); itr != ColumnMap.end(); itr++)
action((*itr).second);
}
//
struct TConditColForOp: public TColCondOperator{
TConditColForOp(TCellCondOperator& test):Test(test),Cell(0){}
bool operator ()(TCoolGrid::TColumn* col)
{
Cell = col->FirstThat(Test);
return Cell != 0;
}
TCellCondOperator& Test;
TCoolGrid::TCell* Cell;
};
//
TCoolGrid::TCell*
TCoolGrid::FirstThat(TCellCondOperator& test)
{
TConditColForOp op(test);
return op.Cell;
}
//
struct TConditColLastOp: public TColCondOperator{
TConditColLastOp(TCellCondOperator& test):Test(test),Cell(0){}
bool operator ()(TCoolGrid::TColumn* col)
{
Cell = col->LastThat(Test);
return Cell != 0;
}
TCellCondOperator& Test;
TCoolGrid::TCell* Cell;
};
//
TCoolGrid::TCell*
TCoolGrid::LastThat(TCellCondOperator& test)
{
TConditColLastOp op(test);
LastThat(op);
return op.Cell;
}
//
struct TActionColOp: public TColActionOperator{
TActionColOp(TCellActionOperator& action):Action(action){}
void operator ()(TCoolGrid::TColumn* col)
{
col->ForEach(Action);
}
TCellActionOperator& Action;
};
//
void TCoolGrid::ForEach(TCellActionOperator& action)
{
TActionColOp op(action);
ForEach(op);
}
//
// Respond to WM_SYSCOLORCHANGE to let the cells update their UI colors, and
// to let this grig window update its background color.
//
//
struct TSysColorChangeOp: public TCellActionOperator{
void operator ()(TCoolGrid::TCell* cell)
{ cell->SysColorChange(); }
};
void TCoolGrid::EvSysColorChange()
{
TSysColorChangeOp op;
ForEach(op);
}
//
void TCoolGrid::SetFont(const TFont& font)
{
delete Font;
Font = new TFont(font);
}
//
void TCoolGrid::SetBoldFont(const TFont& font)
{
delete BoldFont;
BoldFont = new TFont(font);
}
//
void TCoolGrid::SetCell(const TCellPos& pos, TCell& cell)
{
TColumn* column = CreateColumn(pos.col);
column->SetCell(pos.row, cell);
if(pos.row >= RowCount)
RowCount = pos.row+1;
if(pos.col >= ColCount)
ColCount = pos.col+1;
}
//
void TCoolGrid::RemoveCell(const TCellPos& pos)
{
TColumnMap::iterator itr = ColumnMap.find(pos.col);
CHECK(itr != ColumnMap.end());
if(itr != ColumnMap.end())
(*itr).second->RemoveCell(pos.row);
}
//
TCoolGrid::TColumn*
TCoolGrid::CreateColumn(int loc)
{
TColumnMap::iterator itr = ColumnMap.find(loc);
if(itr == ColumnMap.end()){
TColumn* col = (ColBuilder)(*this, loc);
col->Id = loc;
itr = ColumnMap.insert(TColumnMap::value_type(loc, col)).first;
}
return (*itr).second;
}
//
void TCoolGrid::SetInPlaceEdit(TInPlaceEdit* edit)
{
delete InPlaceEdit;
InPlaceEdit = edit;
}
//
void TCoolGrid::GetCellRect(const TCellPos& pos, TRect& rect) const
{
rect.top = Index2Y(pos.row);
if(IsHorizHeader())
rect.top += HeaderHeight+LineHeight;
rect.bottom = rect.top + GetRowHeight(pos.row);
rect.left = Index2X(pos.col);
if(IsVertHeader())
rect.left += HeaderWidth+LineWidth;
rect.right = rect.left + GetColumnWidth(pos.col);
}
//
void TCoolGrid::RemoveColumn(uint loc)
{
TColumnMap::iterator itr = ColumnMap.find(loc);
if(itr != ColumnMap.end()){
delete (*itr).second;
ColumnMap.erase(itr);
}
}
//
TCoolGrid::TColumn*
TCoolGrid::GetColumn(int loc)
{
TColumnMap::iterator itr = ColumnMap.find(loc);
if(itr != ColumnMap.end())
return (*itr).second;
return 0;
}
//
void TCoolGrid::SetColumnEdit(int column, TInPlaceEdit* edit)
{
CreateColumn(column)->SetInPlaceEdit(edit);
}
//
TCoolGrid::TInPlaceEdit*
TCoolGrid::GetColumnEdit(int column)
{
TColumn* col = GetColumn(column);
if(col)
return col->GetInPlaceEdit();
return 0;
}
//
int TCoolGrid::FirstVisibleRow()
{
//int index = X2Index(Scroller->YPos);
int index = Y2Index(1);
if(index==-1)
index = 0;
return index;
}
//
int TCoolGrid::FirstVisibleColumn()
{
//int index = X2Index(Scroller->XPos);
int index = X2Index(1);
if(index==-1)
index = 0;
return index;
}
//
void TCoolGrid::PaintGridLines(TDC& dc, const TRect& rect)
{
dc.SelectObject(TUIFace::GetDitherBrush());
PaintRowLines(dc, rect);
PaintColLines(dc, rect);
dc.RestoreBrush();
}
//
static uint raster_op = PATCOPY; // PATINVERT
//
void TCoolGrid::PaintRowLines(TDC& dc, const TRect& rect)
{
uint width = rect.Width();
int headerDelta = 0;
int y = -GetTopPos();
if(IsHorizHeader())
headerDelta = HeaderHeight+LineHeight;
y += headerDelta;
int last_index = 0;
for(TDimMap::iterator itr = HeightMap.begin(); itr != HeightMap.end(); itr++){
int index = (*itr).first;
while(last_index < index){
y += Height+LineHeight;
if(y > headerDelta)
VERIFY(dc.PatBlt(rect.left, y, width, LineHeight, raster_op));
last_index++;
}
y += (*itr).second+LineHeight;
if(y > headerDelta)
VERIFY(dc.PatBlt(rect.left, y-1, width, LineHeight, raster_op));
last_index++;
}
for(;last_index < RowCount; last_index++){
y += Height+LineHeight;
if(y > headerDelta)
VERIFY(dc.PatBlt(rect.left, y-1, width, LineHeight, raster_op));
}
}
//
void TCoolGrid::PaintColLines(TDC& dc, const TRect& rect)
{
int height = Index2Y(RowCount-1) + GetRowHeight(RowCount-1);
int delta = 0;
if(IsHorizHeader())
delta += HeaderHeight+LineHeight;
VERIFY(dc.PatBlt(rect.right, rect.top+delta, LineWidth, height-rect.top, raster_op));
}
//
void TCoolGrid::PaintFocusedCell(TDC& dc, const TRect& rect)
{
// paint on DC, not on MemDC, why, maby better would be on MemDC ???
if(IsFlagSet(gfRowSelect)){
// paint full row
TRect rowRect(rect);
rowRect.left = 0;//GetOffsetPos();
rowRect.right = Index2X(ColCount-1)+GetColumnWidth(ColCount-1);
if(IsFlagSet(gfVertHeader))
rowRect.right += HeaderWidth + LineWidth;
if(IsFlagSet(gfNoRowInvert)){
rowRect.Inflate(1,1);
TUIBorder(rowRect, TUIBorder::ButtonDn, TUIBorder::Rect|TUIBorder::Soft).Paint(dc);
}
else
VERIFY(dc.InvertRect(rowRect));
}
else{
TBrush shbr(TColor::Sys3dDkShadow);
VERIFY(dc.FrameRect(rect.InflatedBy(-1, -1), shbr));
//VERIFY(dc.FrameRect(rect.InflatedBy(-1, -1), TUIFace::GetDitherBrush()));
}
}
//
void TCoolGrid::PaintCornerCell(TDC& dc, const TRect& rect)
{
TColor oldClr = dc.SetBkColor(TColor::Sys3dFace);
VERIFY(dc.TextRect(rect));
TUIBorder(rect,TUIBorder::Embossed,TUIBorder::Soft).Paint(dc);
dc.SetBkColor(oldClr);
}
//
void TCoolGrid::PaintDefaultColumn(TDC& dc, const TRect& rect, int index)
{
TRect colmnRect(rect);
int headerDelta = 0;
if(IsFlagSet(gfHorizHeader)){
TRect headerRect(rect);
headerDelta = HeaderHeight + LineHeight;
headerRect.bottom = headerRect.top + headerDelta;
headerRect.right += LineWidth;
PaintHorizHeaderCell(dc, headerRect, index);
colmnRect.top += headerDelta;
}
colmnRect.bottom = Index2Y(RowCount-1) + GetRowHeight(RowCount-1) + headerDelta;
TColor oldClr = dc.SetBkColor(DefColor);
dc.TextRect(colmnRect);
// fill rest area
colmnRect.top = colmnRect.bottom;
colmnRect.bottom = rect.bottom+1;
colmnRect.right++;
dc.SetBkColor(TColor::SysAppWorkspace);
dc.TextRect(colmnRect);
dc.SetBkColor(oldClr);
}
//
void TCoolGrid::PaintHorizHeaderCell(TDC& dc, const TRect& rect, int index)
{
TColor oldClr = dc.SetBkColor(TColor::Sys3dFace);
VERIFY(dc.TextRect(rect));
TUIBorder::TStyle style = TUIBorder::Raised;
TFont* font = GetFont();
if(FocusedCell.Valid() && FocusedCell.col == index && !IsFlagSet(gfRowSelect)){
style = TUIBorder::ButtonUp;
font = GetBoldFont();
}
TUIBorder(rect,style,TUIBorder::Rect|TUIBorder::Soft).Paint(dc);
if(font){
CHECK(font->IsGDIObject());
dc.SelectObject(*font);
}
TRect textRect(rect);
textRect.Inflate(-2,-2);
_TCHAR buffer[80];
wsprintf(buffer, DefHorFormat.c_str(), index);
VERIFY(dc.DrawTextEx(buffer, -1, &textRect, DT_CENTER|DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS));
if(font)
dc.RestoreFont();
dc.SetBkColor(oldClr);
}
//
void TCoolGrid::PaintVertHeaderCell(TDC& dc, const TRect& rect, int index)
{
THeaderCell* cell = 0;
THeaderMap::iterator itr = VertTitles.find(index);
if(itr != VertTitles.end())
cell = (THeaderCell*)(*itr).second;
TColor oldBkClr = dc.SetBkColor(cell ? cell->GetBgColor() : TColor::Sys3dFace);
TColor oldTxClr = dc.SetTextColor(cell ? cell->GetTxColor() : TColor::SysWindowText);
VERIFY(dc.TextRect(rect));
TUIBorder::TStyle style = TUIBorder::Raised;
TFont* font = GetFont();
if(FocusedCell.Valid() && FocusedCell.row == index){
style = TUIBorder::ButtonUp;
font = GetBoldFont();
}
if(font){
CHECK(font->IsGDIObject());
dc.SelectObject(*font);
}
TUIBorder(rect, style, TUIBorder::Rect|TUIBorder::Soft).Paint(dc);
TRect textRect(rect);
textRect.Inflate(-2,-2);
textRect.top++;
if(cell)
cell->Paint(dc, textRect);
else{
_TCHAR buffer[80];
wsprintf(buffer, DefVertFormat.c_str(), index);
VERIFY(dc.DrawTextEx(buffer, -1, &textRect, DT_CENTER|DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS));
}
if(font)
dc.RestoreFont();
dc.SetBkColor(oldBkClr);
dc.SetTextColor(oldTxClr);
}
//
void TCoolGrid::SetDefVertFormat(const owl::tstring& format)
{
DefVertFormat = format;
if(GetHandle())
Invalidate();
}
//
void TCoolGrid::SetDefHorFormat(const owl::tstring& format)
{
DefHorFormat = format;
if(GetHandle())
Invalidate();
}
//
void TCoolGrid::SetHorTitle(uint column, const owl::tstring& text)
{
CreateColumn(column)->SetHeader(text);
if(GetHandle())
Invalidate();
}
//
void TCoolGrid::SetVertTitle(uint row, const owl::tstring& text)
{
THeaderMap::iterator itr = VertTitles.find(row);
if(itr != VertTitles.end())
((THeaderCell*)(*itr).second)->SetText(text.c_str());
else{
THeaderCell* cell = new THeaderCell(text.c_str());
cell->SetParent(this);
VertTitles[row] = cell;
}
if(GetHandle())
Invalidate();
}
//
void TCoolGrid::SetVertTitle(uint row, THeaderCell& cell)
{
THeaderMap::iterator itr = VertTitles.find(row);
if(itr != VertTitles.end()){
delete (*itr).second;
(*itr).second = &cell;
}
else
VertTitles[row] = &cell;
cell.SetParent(this);
if(GetHandle())
Invalidate();
}
//
void TCoolGrid::PaintHeaderColumn(TDC& dc, const TRect& rect)
{
int last_index = 0;
TRect workRect(rect);
int topPos = GetTopPos();
workRect.top -= topPos;
if(IsHorizHeader())
workRect.top += HeaderHeight + LineHeight;
for(TCellMap::iterator itr = VertTitles.begin(); itr != VertTitles.end(); itr++){
if((*itr).first >= last_index){
while(last_index < (*itr).first-1){
int height = GetRowHeight(last_index);
if(0 < Index2Y(last_index) + height){
workRect.bottom = workRect.top + height + LineHeight;
PaintVertHeaderCell(dc, workRect, last_index);
}
workRect.top += height + LineHeight;
last_index++;
}
int height = GetRowHeight(last_index);
if(0 < Index2Y(last_index)+height){
workRect.bottom = workRect.top + height + LineHeight;
PaintVertHeaderCell(dc, workRect, last_index);
}
workRect.top += height + LineHeight;
last_index++;
}
}
for(;last_index < RowCount; last_index++){
int height = GetRowHeight(last_index);
if(0 < Index2Y(last_index)+height){
workRect.bottom = workRect.top + height + LineHeight;
PaintVertHeaderCell(dc, workRect,last_index);
}
workRect.top += height + LineHeight;
}
TColor oldClr = dc.SetBkColor(TColor::SysAppWorkspace);
workRect.bottom = rect.bottom + 1;
workRect.right++;
dc.TextRect(workRect);
dc.SetBkColor(oldClr);
}
//
// Cells always get notified when a left button down occurs within their
// bounding rectangle. If you want mouse drags and a mouse up then you
// need to capture the mouse
//
// Fails if already captured
bool TCoolGrid::CellSetCapture(TCell& cell)
{
if (Capture)
return false;
else {
Capture = &cell;
SetCapture();
return true;
}
}
//
void TCoolGrid::CellReleaseCapture(TCell& cell)
{
if (&cell == Capture) {
Capture = 0;
ReleaseCapture();
}
}
//
↑ V595 The 'Window' pointer was utilized before it was verified against nullptr. Check lines: 1370, 1372.
↑ V595 The 'Window' pointer was utilized before it was verified against nullptr. Check lines: 1394, 1396.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: Id.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: MinDividerIndex.
↑ V1004 The 'grid' pointer was used unsafely after it was verified against nullptr. Check lines: 216, 217.
↑ V1004 The 'grid' pointer was used unsafely after it was verified against nullptr. Check lines: 291, 292.
↑ V1004 The 'grid' pointer was used unsafely after it was verified against nullptr. Check lines: 491, 492.
↑ V1004 The 'cell' pointer was used unsafely after it was verified against nullptr. Check lines: 1122, 1123.
↑ V1004 The 'col' pointer was used unsafely after it was verified against nullptr. Check lines: 1941, 1942.
↑ V522 There might be dereferencing of a potential null pointer 'wnd'.
↑ V560 A part of conditional expression is always false: key == 0x09.
↑ V560 A part of conditional expression is always true: point.y >= (HeaderHeight - HitDelta).
↑ V773 The 'BoldFont' pointer was not released in destructor. A memory leak is possible.
↑ V1027 Pointer to an object of the 'TRect' class is cast to unrelated 'TPoint' class.
↑ V575 The potential null pointer is passed into 'strcpy' function. Inspect the first argument.
↑ V796 It is possible that 'break' statement is missing in switch statement.
↑ V796 It is possible that 'break' statement is missing in switch statement.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V803 Decreased performance. In case 'itr' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.