#include "TCtrlLib.h" #pragma hdrstop #include "CtrlArray.h" namespace Upp { CtrlArray::Item::Item() { SetFrame(OutsetFrame()); array = NULL; NoWantFocus(); // IgnoreMouse(); } CtrlArray::Item::~Item() { array = NULL; } void CtrlArray::Item::Paint(Draw& draw) { draw.DrawRect(GetSize(), IsCursor() ? SWhiteGray : SColorFace()); } void CtrlArray::Item::LeftDown(Point pt, dword keyflags) { SetCursor(); } void CtrlArray::Item::RightDown(Point pt, dword keyflags) { ASSERT(array); SetCursor(); array->RightDown(Null, keyflags); } bool CtrlArray::Key(dword key, int repcnt) { return Bar::Scan(THISBACK(ToolLocal), key); } CtrlArray::CtrlArray() { inserting = removing = duplicating = moving = false; is_closing = false; cursor = -1; height = 0; SetFrame(InsetFrame()); AddFrame(vscroll); vscroll.AutoHide(); vscroll.WhenScroll = THISBACK(OnScroll); vscroll.SetLine(20); Ctrl::Add(scrollview.HSizePos(0, 0)); WhenBar = THISBACK(ToolLocal); } CtrlArray::~CtrlArray() { is_closing = true; items.Clear(); } void CtrlArray::Clear() { items.Clear(); cursor = -1; Layout(); } bool CtrlArray::Accept() { for(int i = 0; i < items.GetCount(); i++) if(!items[i].Accept()) { SetCursor(i); return false; } return true; } int CtrlArray::GetIndex(const Item *item) const { if(item) for(int i = 0; i < items.GetCount(); i++) if(item == &items[i]) return i; return -1; } bool CtrlArray::IsCursor(const Item *item) const { return item && IsCursor() && GetIndex(item) == GetCursor(); } void CtrlArray::SetCursor(const Item *item) { int i = GetIndex(item); if(i >= 0) SetCursor(i); } int CtrlArray::GetYPos(int i) const { int y = 0; while(--i >= 0) y += items[i].GetRect().Height(); return y; } void CtrlArray::OnScroll() { scrollview.TopPos(-vscroll, height); } CtrlArray::Item& CtrlArray::Add() { One item; WhenCreate(item); ASSERT(!!item); Item& new_item = items.Add(-item); Layout(); return new_item; } void CtrlArray::SetCount(int c) { if(cursor >= c) SetCursor(c - 1); while(c > GetCount()) { One item; WhenCreate(item); if(!item) return; items.Add(-item); } if(c < GetCount()) items.Trim(c); Layout(); } void CtrlArray::SetCursor(int at) { if(at >= 0) at = min(at, GetCount() - 1); RefreshCursor(); cursor = minmax(at, -1, GetCount() - 1); if(at >= 0 && at < GetCount()) { Ctrl& item = items[at]; if(!item.HasFocusDeep()) IterateFocusForward(&item, &item); ScrollInto(at); } RefreshCursor(); } void CtrlArray::ScrollInto(int item) { if(item >= 0 && item < items.GetCount()) vscroll.ScrollInto(GetYPos(item), items[item].GetRect().Height()); } void CtrlArray::Layout() { height = 0; while(scrollview.GetFirstChild()) scrollview.GetFirstChild()->Remove(); for(int i = 0; i < items.GetCount(); i++) { items[i].array = this; int iht = items[i].GetRect().Height(); scrollview << items[i].TopPos(height, iht).HSizePos(0, 0); height += iht; } vscroll.Set(vscroll, GetSize().cy, height); OnScroll(); } void CtrlArray::Paint(Draw& draw) { draw.DrawRect(GetSize(), SGray); } void CtrlArray::RightDown(Point pt, dword keyflags) { MenuBar::Execute(WhenBar); } void CtrlArray::MouseWheel(Point pt, int zdelta, dword keyflags) { vscroll.Wheel(zdelta, 3); } void CtrlArray::GotFocus() { RefreshCursor(); } void CtrlArray::LostFocus() { RefreshCursor(); } void CtrlArray::ChildGotFocus() { if(is_closing) return; for(int i = 0; i < items.GetCount(); i++) if(items[i].HasFocusDeep()) { if(i != GetCursor()) SetCursor(i); ScrollInto(i); break; } } void CtrlArray::RefreshCursor() { if(!is_closing && IsCursor()) GetCtrl(GetCursor()).Refresh(); } void CtrlArray::ToolLocal(Bar& bar) { bool hlp = bar.IsScanHelp(); bool ed = IsEditable(); if(hlp || !IsEmpty()) ToolInsertAbove(bar); ToolInsertBelow(bar); ToolUp(bar); ToolDown(bar); bar.MenuSeparator(); ToolDuplicate(bar); ToolRemove(bar); } void CtrlArray::ToolInsertAbove(Bar& bar) { bar.Add(IsEditable() && inserting && (bar.IsScanHelp() || !IsEmpty()), "Vložit nad", THISBACK1(OnInsert, cursor)) .Key(K_CTRL_INSERT) .Help("Vložit nový řádek nad aktuální řádek"); } void CtrlArray::ToolInsertBelow(Bar& bar) { bar.Add(IsEditable() && inserting, bar.IsScanHelp() || !IsEmpty() ? "Vložit pod" : "Vložit", THISBACK1(OnInsert, cursor + 1)) .Key(K_INSERT) .Help("Vložit nový řádek pod aktuální řádek"); } void CtrlArray::ToolDuplicate(Bar& bar) { bar.Add(IsEditable() && duplicating && (bar.IsScanHelp() || cursor >= 0), "Duplikovat", THISBACK1(OnDuplicate, cursor)) .Help("Zkopírovat aktuální řádek tabulky na další řádek"); } void CtrlArray::ToolRemove(Bar& bar) { bar.Add(IsEditable() && removing && (bar.IsScanHelp() || cursor >= 0), "Smazat", THISBACK1(OnRemove, cursor)) .Key(K_CTRL_DELETE) .Help("Odstranit aktuální řádek tabulky"); } void CtrlArray::ToolUp(Bar& bar) { bar.Add(IsEditable() && moving && cursor > 0, "Posunout nahoru", THISBACK1(OnUp, cursor)) .Key(K_CTRL_UP) .Help("Posunout aktuální řádek nahoru"); } void CtrlArray::ToolDown(Bar& bar) { bar.Add(IsEditable() && moving && cursor + 1 < items.GetCount(), "Posunout dolů", THISBACK1(OnDown, cursor)) .Key(K_CTRL_DOWN) .Help("Posunout aktuální řádek dolů"); } void CtrlArray::OnInsert(int at) { at = minmax(at, 0, items.GetCount()); One item; WhenCreate(item); if(item) { items.Insert(at, -item); Layout(); SetCursor(at); UpdateAction(); } } void CtrlArray::OnDuplicate(int i) { if(i >= 0 && i < items.GetCount()) { Value v = Get(i); One item; WhenCreate(item); if(item) { items.Insert(i + 1, -item); items[i + 1] <<= v; Layout(); SetCursor(i + 1); UpdateAction(); } } } void CtrlArray::OnRemove(int i) { if(i >= 0 && i < items.GetCount()) { items.Remove(i); cursor = -1; Layout(); SetCursor(min(i, GetCount() - 1)); UpdateAction(); } } void CtrlArray::OnUp(int index) { if(index > 0 && index < items.GetCount()) { items.Swap(index, index - 1); Layout(); SetCursor(index - 1); UpdateAction(); } } void CtrlArray::OnDown(int index) { if(index >= 0 && index + 1 < items.GetCount()) { items.Swap(index, index + 1); Layout(); SetCursor(index + 1); UpdateAction(); } } }