Home » Community » Newbie corner » Custom/Weird Array Setup
Custom/Weird Array Setup [message #46209] |
Sat, 26 March 2016 12:01 |
bempson
Messages: 8 Registered: March 2016
|
Promising Member |
|
|
I've been mucking around with this for a bit. Was wondering if an ArrayCtrl could be set up like the application image attached.
I would assume that would be a custom widget, with the blue text being some sort of special row attached to the standard row, but I don't know.
Is it possible to get the blue text that spans multiple columns working easily or is this strictly a custom widget setup?
Thank you,
Brian
|
|
|
|
Re: Custom/Weird Array Setup [message #46213 is a reply to message #46209] |
Sat, 26 March 2016 23:22 |
Novo
Messages: 1371 Registered: December 2006
|
Ultimate Contributor |
|
|
A good example could be an "Error" grid in TheIDE. It is declared as an Ide::error member of type ArrayCtrl. All logic is implemented by the class ElepDisplay (file uppsrc\ide\Errors.cpp).
Regards,
Novo
|
|
|
|
Re: Custom/Weird Array Setup [message #46216 is a reply to message #46209] |
Sun, 27 March 2016 10:50 |
bempson
Messages: 8 Registered: March 2016
|
Promising Member |
|
|
Here is my progress so far.
The red portion is a custom display I set up to render text in that area, seems to be working fine.
I had to subclass ArrayCtrl, modify ArrayCtrl to expose certain private variables (the paint() method depends upon them), and modify the paint() routine to paint my special display after all of the columns in the row.
It's ugly (oh man I changed a base class to do it! yuck!), it's kludgy, but hey, it works so far.
I have a question, if I am drawing text in the red area, how can I notify the Ctrl class itself about the size needed to accomodate the text? Right now the values are statically assigned, but I will need to fix this so that somehow, the paint() routing would have some sort of hint as to the size (height) of the rectangle needed for a certain amount of text.
Any suggestions?
[Updated on: Sun, 27 March 2016 10:50] Report message to a moderator
|
|
|
|
|
Re: Custom/Weird Array Setup [message #46222 is a reply to message #46221] |
Mon, 28 March 2016 01:31 |
Lance
Messages: 549 Registered: March 2007
|
Contributor |
|
|
Here is the code:
#include <GridCtrl/GridCtrl.h>
#include <RichText/RichText.h>
using namespace Upp;
// An adhoc protocol
// A cell will merge all consective cells right to it that are with Null value.
//
// note, there is still (at least) one missing piece, the text is not clipped to cell rect
class QtfGridDisplay : public GridDisplay {
public:
virtual void Paint(Draw& w, int x, int y, int cx, int cy, const Value& val, dword style,
Color& fg, Color& bg, Font& fnt, bool found, int fs, int fe)
{
GridCtrl *p=this->parent;
Color rbg=parent->Get(row,0)==1 ? Color(0,250,128) : bg;
int realcx=cx;
if(col!=1 && IsNull(p->Get(row,col)))
return; // the cell is merged, so no painting for it
for(int c=col+1; c<p->GetColumnCount();++c)
if(IsNull(p->Get(row,c)))
realcx+=p->GetWidth(c+2);
else
break;
w.DrawRect(x,y,realcx,cy, rbg);
DrawSmartText(w,x,y,realcx,String(val),fnt,fg);
}
static QtfGridDisplay& get(){ static QtfGridDisplay d; return d; }
};
class GridHilite : public TopWindow {
public:
typedef GridHilite CLASSNAME;
GridHilite();
private:
GridCtrl grid1;
};
GridHilite::GridHilite()
{
grid1.AddHiddenColumn("bg"); // hidden column with value 1 will be painted with a greenish background
grid1.AddColumn("Label");
grid1.AddColumn("Action");
grid1.AddColumn("NFC");
grid1.AddColumn("Description");
String s="\1[ [ [*+75 Set Flags]&][ [@5+75 MiguelFollowing`=true]&][ [@5+75 MiguelLeaving`=false]&][ [@5+75 MiguleWandering`=false]]]";
grid1.AddRow(1,"\1[*+75 Wander]",s).SetDisplay(QtfGridDisplay::get()).Height(GetSmartTextHeight(s,500));
grid1.AddRow(0,"","\1[*+75 Trigger]","","\1[*+75Trigger nsfwander]").SetDisplay(QtfGridDisplay::get());
// Here are 4 plain text, I will put it in the 2nd column, and make it with hilite background;
String s1="Line 1";
String s2="grid1.VertGrid(false).HSizePosZ(2,2).VSizePosZ(2,2)";
String s3="grid1.AddColumn(\"Description\")";
String s4="OK, that's about it";
String combined=String().Cat()<<'\1'<<"[ [ [*+75 "<<DeQtf(s1)<<"]&]"
"[ [@5+75 "<<DeQtf(s2)<<"]&]" // use DeQtf to escape certain special characters
"[ [@5+75 "<<DeQtf(s3)<<"]&]" // use MainMenu->Assist->QtfDesigner to get markup strings.
"[ [@5+75 "<<DeQtf(s4)<<"]]";
grid1.AddRow(1,"",combined).SetDisplay(QtfGridDisplay::get())
.Height(GetSmartTextHeight(s,500));
grid1.VertGrid(false).HSizePosZ(2,2).VSizePosZ(2,2);
Add(grid1);
}
GUI_APP_MAIN
{
GridHilite().Run();
}
|
|
|
|
|
|
Re: Custom/Weird Array Setup [message #46247 is a reply to message #46246] |
Fri, 01 April 2016 21:38 |
Lance
Messages: 549 Registered: March 2007
|
Contributor |
|
|
To save you some search into GridCtrl code. Also, text clipping added.
#include <GridCtrl/GridCtrl.h>
#include <RichText/RichText.h>
using namespace Upp;
// An adhoc protocol
// A cell will merge all consective cells right to it and with Null value.
//
// note, there is still (at least) one missing piece, the text is not clipped to cell rect
class QtfGridDisplay : public GridDisplay {
public:
virtual void Paint(Draw& w, int x, int y, int cx, int cy, const Value& val, dword style,
Color& fg, Color& bg, Font& fnt, bool found, int fs, int fe)
{
GridCtrl *p=this->parent;
Color rbg=parent->Get(row,0)!=1? bg: (style&GD::CURSOR)? Color(0,200,85):Color(0,250,128);
int realcx=cx;
if(col!=1 && IsNull(p->Get(row,col)))
return; // the cell is merged, so no painting for it
for(int c=col+1; c<p->GetColumnCount();++c)
if(IsNull(p->Get(row,c)))
realcx+=p->GetWidth(c+2);
else
break;
w.DrawRect(x,y,realcx,cy, rbg);
w.Clip(x,y,realcx,cy);
DrawSmartText(w,x,y,realcx,String(val),fnt,fg);
w.End();
}
static QtfGridDisplay& get(){ static QtfGridDisplay d; return d; }
};
class GridHilite : public TopWindow {
public:
typedef GridHilite CLASSNAME;
GridHilite();
private:
GridCtrl grid1;
};
GridHilite::GridHilite()
{
grid1.AddHiddenColumn("bg");
grid1.AddColumn("Label");
grid1.AddColumn("Action");
grid1.AddColumn("NFC");
grid1.AddColumn("Description");
grid1.SetDisplay(QtfGridDisplay::get());
String s="\1[ [ [*+75 Set Flags]&][ [@5+75 MiguelFollowing`=true]&][ [@5+75 MiguelLeaving`=false]&][ [@5+75 MiguleWandering`=false]]]";
grid1.AddRow(1,"\1[*+75 Wander]",s).Height(GetSmartTextHeight(s,500));
//grid1.JoinCells(2,0,4,0);
grid1.AddRow(0,"","\1[*+75 Trigger]","","\1[*+75Trigger nsfwander]");
// Here are 4 plain text, I will put it in the 2nd column, and make it with hilite background;
String s1="Line 1";
String s2="grid1.VertGrid(false).HSizePosZ(2,2).VSizePosZ(2,2)";
String s3="grid1.AddColumn(\"Description\")";
String s4="OK, that's about it";
String combined=String().Cat()<<'\1'<<"[ [ [*+75 "<<DeQtf(s1)<<"]&]"
"[ [@5+75 "<<DeQtf(s2)<<"]&]" // use DeQtf to escape certain special characters
"[ [@5+75 "<<DeQtf(s3)<<"]&]" // use MainMenu->Assist->QtfDesigner to get markup strings.
"[ [@5+75 "<<DeQtf(s4)<<"]]";
grid1.AddRow(1,"",combined,Null,"\1[*+75 Here]")
.Height(GetSmartTextHeight(s,500));
grid1.VertGrid(false).HSizePosZ(2,2).VSizePosZ(2,2);
Add(grid1);
}
GUI_APP_MAIN
{
GridHilite().Run();
}
[Updated on: Fri, 01 April 2016 21:39] Report message to a moderator
|
|
|
|
|
Re: Custom/Weird Array Setup [message #46257 is a reply to message #46209] |
Sun, 03 April 2016 01:33 |
bempson
Messages: 8 Registered: March 2016
|
Promising Member |
|
|
I thought I would post the code for the version I made just in case anyone was wondering. I also have a screenshot of the result. It's not optimal (because of the base class modifications you need), this is the result of solving the problem with brute force instead of looking for a more correct solution:
#ifndef eventtablehpp_h
#define eventtablehpp_h
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct CellDisplay : public Display
{
void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
w.DrawRect(r,paper);
DrawSmartText(w,r.TopLeft().x,r.TopLeft().y-5,5000,String(q),StdFont(),Color(0,0,0));
}
};
struct CellExtDisplay : public Display
{
void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
{
w.DrawRect(r,paper);
DrawSmartText(w,r.TopLeft().x,r.TopLeft().y-10,r.BottomRight().x - r.TopLeft().x,String(q),StdFont(),Color(0,0,0));
}
};
class EventTableCtrl : public ArrayCtrl {
public:
EventTableCtrl();
void SetExtData(int,const Value&);
void SetExtDisplay(const Display&);
void SetDefaultColumnDisplay(const Display&);
void Paint(Draw&);
int InsertRow(const Value&,const Value&,const Value&,const Value&,const Value&);
void SetRowColor(int,const Color&);
private:
const Display *ext_display;
const Display *column_display;
Vector<Value> ext_value;
Vector<Color> row_color;
};
#endif
#include "eventtable.h"
using namespace Upp;
EventTableCtrl::EventTableCtrl()
: ext_display(&Single<CellExtDisplay>()), column_display(&Single<CellDisplay>())
{
NoPopUpEx();
AddColumn("Label").SetDisplay(*column_display);
AddColumn("Action").SetDisplay(*column_display);
AddColumn("Actor").SetDisplay(*column_display);
AddColumn("Description").SetDisplay(*column_display);
}
void EventTableCtrl::SetExtData(int n,const Value& v)
{
ext_value.Insert(n,v);
}
void EventTableCtrl::SetExtDisplay(const Display& d)
{
ext_display = &d;
}
void EventTableCtrl::SetDefaultColumnDisplay(const Display& d)
{
column_display = &d;
}
void EventTableCtrl::SetRowColor(int row,const Color& color)
{
row_color[row] = color;
}
int EventTableCtrl::InsertRow(const Value& label,const Value& action,const Value& npc,const Value& desc,const Value& ext)
{
int rc = GetCount();
Vector<Value> vals;
vals.push_back(String().Cat()<<"\1 [ [*+60 "<<label.ToString()<<"]]");
vals.push_back(String().Cat()<<"\1 [ [*+60 "<<action.ToString()<<"]]");
vals.push_back(String().Cat()<<"\1 [ [*+60 "<<npc.ToString()<<"]]");
vals.push_back(String().Cat()<<"\1 [ [*+60 "<<desc.ToString()<<"]]");
if(!ext.IsNull())
SetExtData(rc,String().Cat()<<"\1 [ [ [@5+50 "<<ext.ToString()<<"]]");
else
SetExtData(rc,Value());
Insert(rc,vals);
row_color.push_back(Color(255,255,255));
return rc;
}
void EventTableCtrl::Paint(Draw& w)
{
SyncColumnsPos();
bool hasfocus0 = HasFocusDeep();
Size size = GetSize();
Rect r;
r.bottom = 0;
int i = GetLineAt(GetScroll());
int xs = -HeaderObject().GetScroll();
int js;
for(js = 0; js < GetColumnCount(); js++) {
int cw = HeaderObject().GetTabWidth(js);
if ((xs + cw - 0 + (js == GetColumnCount() - 1)) >= 0)
break;
xs += cw;
}
int sy = 0;
int dr = HeaderObject().GetTabWidth(0);
int extlsz = size.cx-dr;
if(!IsNull(i))
while(i < GetCount()) {
int lineYSize=20;
if(!ext_value[i].IsNull())
{
lineYSize += GetSmartTextHeight(ext_value[i].ToString(),extlsz);
lineYSize += 5; //Row lower margin
}
SetLineCy(i, lineYSize);
r.top = GetLineY(i) - GetScroll();
if(r.top > size.cy)
break;
r.bottom = r.top + GetLineCy(i);
int x = xs;
dword st = 0;
int tw = 0;
Rect h = r;
for(int j = js; j < GetColumnCount(); j++)
{
tw += HeaderObject().Tab(j).GetMargin();
}
for(int j = js; j < GetColumnCount(); j++) {
int cw = HeaderObject().GetTabWidth(j);
int jj = HeaderObject().GetTabIndex(j);
int cm = HeaderObject().Tab(j).GetMargin();
if(x > size.cx) break;
r.left = x;
r.right = x + cw - 0 + (j == GetColumnCount() - 1);
dword st;
Color fg, bg;
Value q;
const Display& d = GetCellInfo(i, jj, hasfocus0, q, fg, bg, st);
(st&Display::CURSOR) ? bg=Color(0,200,230) : bg=row_color[i];
if(w.IsPainting(r)) {
if(cw < 2 * cm || editmode && i == cursor/* && ColumnAt(jj).edit*/)
d.PaintBackground(w, r, q, fg, bg, st);
else {
d.PaintBackground(w, RectC(r.left, r.top, cm, r.Height()), q, fg, bg, st);
r.left += cm;
r.right -= cm;
d.PaintBackground(w, RectC(r.right, r.top, cm, r.Height()), q, fg, bg, st);
w.Clip(r);
GetDisplay(i, jj).Paint(w, r, q, fg, bg, st);
w.End();
}
}
x += cw;
}
if(ext_display && !ext_value[i].IsNull())
{
dword st;
Color fg, bg;
ext_display->Paint(w,RectC(dr, r.top+20, extlsz, h.Height()), ext_value[i], fg, bg, st);
}
//if(horzgrid)
w.DrawRect(0, r.bottom, size.cx, 1, gridcolor);
r.left = 0;
r.right = x;
if(i == cursor && !nocursor && multiselect && (GetSelectCount() != 1 || !IsSel(i)) && hasfocus0 && !isdrag)
DrawFocus(w, r, st & Display::SELECT ? SColorPaper() : SColorText());
r.bottom += horzgrid;
r.left = x;
r.right = size.cx;
if(!nobg)
w.DrawRect(r, SColorPaper);
if(i == dropline && dropcol == DND_INSERTLINE)
DrawHorzDrop(w, 0, r.top - (i > 0), size.cx);
sy = r.bottom;
i++;
}
int ldy = r.bottom;
r.left = 0;
r.right = size.cx;
r.top = r.bottom;
if(IsAppendLine() && !IsCursor()) {
r.bottom = r.top + linecy;
w.DrawRect(r, HasFocus() ? SColorHighlight : SColorFace);
r.top = r.bottom;
}
r.bottom = size.cy;
if(!nobg)
w.DrawRect(r, SColorPaper);
if(GetCount() == dropline && dropcol == DND_INSERTLINE)
DrawHorzDrop(w, 0, ldy - 1, size.cx);
scroller.Set(Point(header.GetScroll(), sb));
return;
}
It overrides the Paint() method of ArrayCtrl to do the wizardry that should be done with displays as mentioned by Lance above. To get this to compile you need to change several "private" sections in ArrayCtrl.h to "protected" to expose some of the functions and members the Paint() method needs.
[Updated on: Sun, 03 April 2016 01:36] Report message to a moderator
|
|
|
Re: Custom/Weird Array Setup [message #46266 is a reply to message #46257] |
Sun, 03 April 2016 14:10 |
Lance
Messages: 549 Registered: March 2007
|
Contributor |
|
|
Thanks for sharing, bempson. Nice job! I know your pain. Some U++ classes is hard to derive from. Or probably they are not meant to be derived for unknown reason.
|
|
|
Goto Forum:
Current Time: Sat Sep 21 03:00:14 CEST 2024
Total time taken to generate the page: 0.18137 seconds
|