diff --git a/uppsrc/CtrlLib/CtrlLib.upp b/uppsrc/CtrlLib/CtrlLib.upp index 3fe6fa200..aa15027fd 100644 --- a/uppsrc/CtrlLib/CtrlLib.upp +++ b/uppsrc/CtrlLib/CtrlLib.upp @@ -72,6 +72,7 @@ file TreeCtrl readonly separator, TreeCtrl.h, TreeCtrl.cpp, + DropTree.cpp, DlgColor readonly separator, DlgColor.h, DlgColor.cpp, diff --git a/uppsrc/CtrlLib/DropTree.cpp b/uppsrc/CtrlLib/DropTree.cpp new file mode 100644 index 000000000..65e2c0ae4 --- /dev/null +++ b/uppsrc/CtrlLib/DropTree.cpp @@ -0,0 +1,218 @@ +#include "CtrlLib.h" + +namespace Upp { + +CH_VALUE(TreeDropEdge, ChBorder(BlackBorder())); + +CtrlFrame& TreeDropFrame() +{ + static LookFrame m(TreeDropEdge); + return m; +} + +PopUpTree::PopUpTree() { + SetFrame(TreeDropFrame()); + Accel(); + MouseMoveCursor(); + NoPopUpEx(); + maxheight = INT_MAX; + open = autosize = false; + showpos = Null; + WhenOpen = WhenClose = THISBACK(OpenClose); + droplines = 16; +} + +PopUpTree::~PopUpTree() {} + +void PopUpTree::CancelMode() { + if(open) { + DoClose(); + WhenCancel(); + } + TreeCtrl::CancelMode(); +} + +void PopUpTree::DoClose() { + open = false; + Ctrl::Close(); +} + +void PopUpTree::Deactivate() { + if(open) { + DoClose(); + IgnoreMouseClick(); + WhenCancel(); + } +} + +void PopUpTree::Select() { + if(IsCursor() && !GetData().IsVoid()) { + DoClose(); + WhenSelect(); + } +} + +bool PopUpTree::Key(dword key, int n) { + switch(key) { + case K_ENTER: + case K_ALT_DOWN: + DoClose(); + WhenSelect(); + return true; + case K_ESCAPE: + DoClose(); + WhenCancel(); + return true; + } + return TreeCtrl::Key(key, n); +} + +void PopUpTree::PopUp(Ctrl *owner, int x, int top, int bottom, int width) { + DoClose(); + Rect area = Ctrl::GetWorkArea(); + int mh = min(maxheight, area.bottom - bottom); + int h = AddFrameSize(width, maxheight).cy; + showpos.x = x; + showpos.y = bottom; + showwidth = width; + up = false; + if(showpos.y + h > area.bottom) { + up = true; + showpos.y = top; + } + open = false; + Ctrl popup; + int ht = AddFrameSize(width, min(mh, autosize ? GetTreeSize().cy : droplines * GetStdFontCy())).cy; + Rect rt = RectC(showpos.x, showpos.y - (up ? ht : 0), showwidth, ht); + if(GUI_PopUpEffect()) { + if(up) { + popup.SetRect(Rect(rt.left, rt.bottom - 1, rt.right, rt.bottom)); + popup.Add(TopPos(0, rt.Height()).LeftPos(0, rt.Width())); + } + else { + popup.SetRect(Rect(rt.left, rt.top, rt.right, rt.top + 1)); + popup.Add(BottomPos(0, rt.Height()).LeftPos(0, rt.Width())); + } + CenterCursor(); + popup.PopUp(owner, true, true, GUI_DropShadows()); + SetFocus(); + Ctrl::ProcessEvents(); + Animate(popup, rt, GUIEFFECT_SLIDE); + Ctrl::Remove(); + } + CenterCursor(); + SetRect(rt); + Ctrl::PopUp(owner, true, true, GUI_DropShadows()); + SetFocus(); + open = true; +} + +void PopUpTree::OpenClose(int) +{ + if(autosize) { + SyncTree(); + Rect area = Ctrl::GetWorkArea(); + int mh = min(maxheight, area.bottom - showpos.y); + int ht = AddFrameSize(showwidth, min(mh, GetTreeSize().cy)).cy; + SetRect(RectC(showpos.x, showpos.y - (up ? ht : 0), showwidth, ht)); + } +} + +void PopUpTree::PopUp(Ctrl *owner, int width) +{ + Rect r = owner->GetScreenRect(); + r.right = r.left + width; + PopUp(owner, r.left, r.top, r.bottom, width); + if(IsNull(showpos)) + showpos = r.TopLeft(); + OpenClose(0); +} + +void PopUpTree::PopUp(Ctrl *owner) +{ + Rect r = owner->GetScreenRect(); + PopUp(owner, r.left, r.top, r.bottom, r.Width()); +} + +void DropTree::Sync() { + Image icon; + if(tree.IsCursor()) + icon = tree.GetNode(tree.GetCursor()).image; + icond.Set(valuedisplay ? *valuedisplay : tree.GetDisplay(tree.GetCursor()), icon); + MultiButton::SetDisplay(icond); + Set(tree.Get()); +} + +bool DropTree::Key(dword k, int) { + if(IsReadOnly()) return false; + if(k == K_ALT_DOWN) { + Drop(); + return true; + } + return false; +} + +void DropTree::Drop() { + if(IsReadOnly()) return; + if(dropfocus) + SetFocus(); + WhenDrop(); + tree.PopUp(this, GetRect().GetWidth()); +} + +void DropTree::Select() { + if(dropfocus) + SetFocus(); + Sync(); + UpdateAction(); +} + +void DropTree::Cancel() { + if(dropfocus) + SetFocus(); + Sync(); +} + +void DropTree::Clear() { + tree.Clear(); + tree <<= Null; + Sync(); + Update(); +} + +void DropTree::SetData(const Value& data) +{ + tree <<= data; + if(tree.Get() != data) { + tree <<= data; + Update(); + Sync(); + } +} + +Value DropTree::GetData() const +{ + return notnull && IsNull(tree.Get()) ? NotNullError() : tree.Get(); +} + +DropTree& DropTree::ValueDisplay(const Display& d) +{ + valuedisplay = &d; + Sync(); + return *this; +} + +DropTree::DropTree() +{ + displayall = false; + valuedisplay = NULL; + dropfocus = false; + notnull = false; + AddButton().Main().WhenPush = THISBACK(Drop); + NoInitFocus(); + tree.WhenSelect = THISBACK(Select); + tree.WhenCancel = THISBACK(Cancel); + dropwidth = 0; +} + +}; \ No newline at end of file diff --git a/uppsrc/CtrlLib/TreeCtrl.cpp b/uppsrc/CtrlLib/TreeCtrl.cpp index 5b9991e10..9533ac56d 100644 --- a/uppsrc/CtrlLib/TreeCtrl.cpp +++ b/uppsrc/CtrlLib/TreeCtrl.cpp @@ -278,6 +278,13 @@ void TreeCtrl::SetDisplay(int id, const Display& display) Dirty(id); } +const Display& TreeCtrl::GetDisplay(int id) const +{ + if(id >= 0 && id < item.GetCount() && item[id].display) + return *item[id].display; + return *display; +} + void TreeCtrl::SetNode(int id, const TreeCtrl::Node& n) { (TreeCtrl::Node&)item[id] = n; @@ -808,10 +815,12 @@ void TreeCtrl::DoClick(Point p, dword flags, bool down) anchor = cursor; } } - if(cursor != q) + if(cursor != q) { WhenAction(); + } if(down) WhenLeftClick(); + Select(); } } @@ -960,9 +969,9 @@ void TreeCtrl::Paint(Draw& w) int x = 0; x = levelcx + l.level * levelcx - org.x; Point op = Point(x - levelcx2, y + msz.cy / 2); - Rect r = RectC(x, y, vsz.cx + 2 * m.margin, msz.cy); + Rect fr = RectC(x, y, vsz.cx + 2 * m.margin + isz.cx, msz.cy); if(l.itemi == dropitem) { - dri = r; + dri = fr; if(i == 0) dri.top++; } @@ -992,7 +1001,7 @@ void TreeCtrl::Paint(Draw& w) } if(i == cursor && !nocursor && multiselect && GetSelectCount() != 1 && HasFocus() && !IsDragAndDropTarget()) - DrawFocus(w, r, st & Display::SELECT ? SColorPaper() : SColorText()); + DrawFocus(w, fr, st & Display::SELECT ? SColorPaper() : SColorText()); } } } @@ -1081,6 +1090,9 @@ bool TreeCtrl::Key(dword key, int) bool shift = key & K_SHIFT; key &= ~K_SHIFT; switch(key) { + case K_ENTER: + Select(); + break; case K_TAB: return Tab(1); case K_SHIFT_TAB: @@ -1385,6 +1397,10 @@ void TreeCtrl::SetOption(int id) { } +void TreeCtrl::Select() +{ +} + void TreeCtrl::DnD(int itemid, int insert) { if(itemid != dropitem || insert != dropinsert) @@ -1693,127 +1709,4 @@ int Copy(TreeCtrl& dst, int did, int i, const TreeCtrl& src, int id) return did; } -CH_VALUE(TreeDropEdge, ChBorder(BlackBorder())); - -CtrlFrame& TreeDropFrame() -{ - static LookFrame m(TreeDropEdge); - return m; -} - -PopUpTree::PopUpTree() { - SetFrame(TreeDropFrame()); - Accel(); - MouseMoveCursor(); - NoPopUpEx(); - maxheight = 200; - open = false; - WhenOpen = WhenClose = THISBACK(OpenClose); -} - -PopUpTree::~PopUpTree() {} - -void PopUpTree::CancelMode() { - if(open) { - DoClose(); - WhenCancel(); - } - TreeCtrl::CancelMode(); -} - -void PopUpTree::DoClose() { - open = false; - Ctrl::Close(); -} - -void PopUpTree::Deactivate() { - if(open) { - DoClose(); - IgnoreMouseClick(); - WhenCancel(); - } -} - -void PopUpTree::LeftUp(Point p, dword keyflags) { - TreeCtrl::LeftUp(p, keyflags); - if(IsCursor() && !GetData().IsVoid()) { - DoClose(); - WhenSelect(); - } -} - -bool PopUpTree::Key(dword key, int n) { - switch(key) { - case K_ENTER: - case K_ALT_DOWN: - DoClose(); - WhenSelect(); - return true; - case K_ESCAPE: - DoClose(); - WhenCancel(); - return true; - } - return TreeCtrl::Key(key, n); -} - -void PopUpTree::PopUp(Ctrl *owner, int x, int top, int bottom, int width) { - DoClose(); - int h = AddFrameSize(width, maxheight).cy; - showpos.x = x; - showpos.y = bottom; - showwidth = width; - Rect area = Ctrl::GetWorkArea(); - up = false; - if(showpos.y + h > area.bottom) { - up = true; - showpos.y = top; - } - open = false; - Ctrl popup; - int ht = AddFrameSize(width, min(maxheight, GetTreeSize().cy)).cy; - Rect rt = RectC(showpos.x, showpos.y - (up ? ht : 0), showwidth, ht); - if(GUI_PopUpEffect()) { - if(up) { - popup.SetRect(Rect(rt.left, rt.bottom - 1, rt.right, rt.bottom)); - popup.Add(TopPos(0, rt.Height()).LeftPos(0, rt.Width())); - } - else { - popup.SetRect(Rect(rt.left, rt.top, rt.right, rt.top + 1)); - popup.Add(BottomPos(0, rt.Height()).LeftPos(0, rt.Width())); - } - CenterCursor(); - popup.PopUp(owner, true, true, GUI_DropShadows()); - SetFocus(); - Ctrl::ProcessEvents(); - Animate(popup, rt, GUIEFFECT_SLIDE); - Ctrl::Remove(); - } - CenterCursor(); - SetRect(rt); - Ctrl::PopUp(owner, true, true, GUI_DropShadows()); - SetFocus(); - open = true; -} - -void PopUpTree::OpenClose(int i) -{ - SyncTree(); - int ht = AddFrameSize(showwidth, min(maxheight, GetTreeSize().cy)).cy; - SetRect(RectC(showpos.x, showpos.y - (up ? ht : 0), showwidth, ht)); -} - -void PopUpTree::PopUp(Ctrl *owner, int width) -{ - Rect r = owner->GetScreenRect(); - r.right = r.left + width; - PopUp(owner, r.left, r.top, r.bottom, width); -} - -void PopUpTree::PopUp(Ctrl *owner) -{ - Rect r = owner->GetScreenRect(); - PopUp(owner, r.left, r.top, r.bottom, r.Width()); -} - END_UPP_NAMESPACE diff --git a/uppsrc/CtrlLib/TreeCtrl.h b/uppsrc/CtrlLib/TreeCtrl.h index d6fc5d7c1..477370ea9 100644 --- a/uppsrc/CtrlLib/TreeCtrl.h +++ b/uppsrc/CtrlLib/TreeCtrl.h @@ -157,6 +157,7 @@ private: protected: virtual void SetOption(int id); void SyncTree(); + virtual void Select(); public: Callback1 WhenOpen; @@ -207,6 +208,7 @@ public: void Set(int id, Value key, Value value); void SetDisplay(int id, const Display& display); + const Display& GetDisplay(int id) const; void RefreshItem(int id) { RefreshItem(id, 0); } int GetLineCount(); @@ -355,6 +357,24 @@ public: }; class PopUpTree : public TreeCtrl { +public: + virtual void Deactivate(); + virtual void Select(); + virtual bool Key(dword key, int); + virtual void CancelMode(); + +private: + int maxheight; + Point showpos; + bool autosize; + int showwidth; + bool up; + bool open; + int droplines; + + void DoClose(); + void OpenClose(int i); + public: typedef PopUpTree CLASSNAME; PopUpTree(); @@ -369,21 +389,53 @@ public: PopUpTree& MaxHeight(int maxheight_) { maxheight = maxheight_; return *this; } int GetMaxHeight() const { return maxheight; } + PopUpTree& AutoResize(bool b = true) { autosize = b; return *this; } + PopUpTree& SetDropLines(int n) { droplines = n; return *this; } +}; + +class DropTree : public MultiButton { +public: + virtual bool Key(dword k, int cnt); + virtual void SetData(const Value& data); + virtual Value GetData() const; + +private: + PopUpTree tree; + const Display *valuedisplay; + DisplayWithIcon icond; + int dropwidth; + bool displayall; + bool dropfocus; + bool notnull; + + void Sync(); + void Drop(); + void Select(); + void Cancel(); + + typedef DropTree CLASSNAME; public: - virtual void Deactivate(); - virtual void LeftUp(Point p, dword keyflags); - virtual bool Key(dword key, int); - virtual void CancelMode(); + Callback WhenDrop; -protected: - void DoClose(); - void OpenClose(int i); + void Clear(); -protected: - int maxheight; - Point showpos; - int showwidth; - bool up; - bool open; -}; + PopUpTree& TreeObject() { return tree; } + + TreeCtrl *operator->() { return &tree; } + const TreeCtrl *operator->() const { return &tree; } + + DropTree& MaxHeight(int maxheight_) { tree.MaxHeight(maxheight_); return *this; } + DropTree& AutoResize(bool b = true) { tree.AutoResize(b); return *this; } + + DropTree& ValueDisplay(const Display& d); + DropTree& DisplayAll(bool b = true) { displayall = b; return *this; } + DropTree& DropFocus(bool b = true) { dropfocus = b; return *this; } + DropTree& NoDropFocus() { return DropFocus(false); } + DropTree& AlwaysDrop(bool e); + DropTree& SetDropLines(int d) { tree.SetDropLines(d); return *this; } + DropTree& DropWidth(int w) { dropwidth = w; return *this; } + DropTree& DropWidthZ(int w) { dropwidth = HorzLayoutZoom(w); return *this; } + + DropTree(); +}; \ No newline at end of file diff --git a/uppsrc/CtrlLib/init b/uppsrc/CtrlLib/init index 8d7d9f9c7..2acf473cb 100644 --- a/uppsrc/CtrlLib/init +++ b/uppsrc/CtrlLib/init @@ -2,7 +2,7 @@ #define _CtrlLib_icpp_init_stub #include "CtrlCore/init" #include "PdfDraw/init" -#define BLITZ_INDEX__ F0B03D5D3AD4DE5D8FCD3A246E4FAC29A +#define BLITZ_INDEX__ F772FB1BDED2795578D50B5F523477E45 #include "CtrlLib.icpp" #undef BLITZ_INDEX__ #endif diff --git a/uppsrc/Draw/Display.cpp b/uppsrc/Draw/Display.cpp index ce9075114..eef3e1d9a 100644 --- a/uppsrc/Draw/Display.cpp +++ b/uppsrc/Draw/Display.cpp @@ -299,6 +299,38 @@ Size DrawingDisplayCls::RatioSize(const Value& q, int cx, int cy) const { const Display& DrawingDisplay() { return Single(); } +void DisplayWithIcon::PaintBackground(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const +{ + display->PaintBackground(w, r, q, ink, paper, style); +} + +void DisplayWithIcon::Paint(Draw& w, const Rect& r0, const Value& q, Color ink, Color paper, dword style) const +{ + Rect r = r0; + if(!IsNull(icon)) { + Size isz = icon.GetSize(); + w.DrawImage(r.left, r.top + max((r.Height() - isz.cy) / 2, 0), icon); + r.left += isz.cx + lspc; + } + display->Paint(w, r, q, ink, paper, style); +} + +Size DisplayWithIcon::GetStdSize(const Value& q) const +{ + Size sz = display->GetStdSize(q); + if(!IsNull(icon)) { + sz.cx += icon.GetSize().cx + lspc; + sz.cy = max(sz.cy, icon.GetSize().cy); + } + return sz; +} + +DisplayWithIcon::DisplayWithIcon() +{ + display = &StdDisplay(); + lspc = 0; +} + Size PaintRect::GetStdSize() const { return display ? display->GetStdSize(value) : Size(0, 0); } diff --git a/uppsrc/Draw/Display.h b/uppsrc/Draw/Display.h index 6a7854825..be97151f9 100644 --- a/uppsrc/Draw/Display.h +++ b/uppsrc/Draw/Display.h @@ -73,6 +73,24 @@ private: String nulltext; }; +class DisplayWithIcon : public Display { + const Display *display; + Image icon; + int lspc; +public: + virtual void PaintBackground(Draw& w, const Rect& r, const Value& q, + Color ink, Color paper, dword style) const; + virtual void Paint(Draw& w, const Rect& r, const Value& q, + Color ink, Color paper, dword style) const; + virtual Size GetStdSize(const Value& q) const; + + void SetIcon(const Image& img, int spc = 4) { icon = img; lspc = spc; } + void SetDisplay(const Display& d) { display = &d; } + void Set(const Display& d, const Image& m, int spc = 4) { SetIcon(m, spc); SetDisplay(d); } + + DisplayWithIcon(); +}; + class PaintRect : Moveable { protected: Value value;