#include "diawxgtk.h" struct TREEELM { char *title; char *key; wxBitmap *icon; }; PUBLIC void TREEMENU::vscroll_func (wxScrollEvent &ev) { setscroll (ev.GetPosition()); } PUBLIC TREEMENU::TREEMENU ( wxFORMBASE *_parent, const char *_id) : MFORM (_parent,_id) { full = rem_getvarval ("mode")==1; vscroll = new wxScrollBar (this,-1,wxDefaultPosition,wxDefaultSize ,wxSB_VERTICAL); vscroll->SetValue (0); voffset = 0; tb = NULL; maxtb = 0; nbtb = 0; terminal = NULL; statopen = NULL; level = NULL; curlevel = 1; stretch_mode = STRETCH_LOOK; } PUBLIC void TREEMENU::setscroll (int newpos) { if (voffset != newpos){ wxClientDC dc(this); int w_width,w_height; GetSize(&w_width,&w_height); int move = (newpos - voffset)*getskipy(); voffset = newpos; if (abs(move) >= w_height || true){ // No cliping needed, since we are moving a whole page // For now, we do it all the time, because blitting does // not work, don't know why. refresh(); }else{ if (move > 0){ int y = w_height - move; dc.Blit (0,0,w_width,y,&dc,0,move); dc.SetClippingRegion (0,y,w_width,move); }else{ int y = w_height + move; dc.Blit (0,-move,w_width,y,&dc,0,0); dc.SetClippingRegion (0,0,w_width,-move); } refresh(); dc.DestroyClippingRegion(); } } } PROTECTED bool TREEMENU::OnCharHook(wxKeyEvent& event) { int ret = TRUE; int viewstart,viewlength,objlength,pagelength; vscroll->GetValues(&viewstart, &viewlength, &objlength, &pagelength); int charh = (int)GetCharHeight(); long key = event.GetKeyCode(); int newoff = voffset; if (key == WXK_DOWN){ newoff += charh; }else if (key == WXK_UP){ newoff -= charh; }else if (key == WXK_PRIOR){ newoff -= pagelength; }else if (key == WXK_NEXT){ newoff += pagelength; }else{ ret = FALSE; } int maxoff = getviewlength() - 400; if (newoff > maxoff) newoff = maxoff; if (newoff < 0) newoff = 0; if (newoff != voffset){ vscroll->SetValue (newoff); setscroll (newoff); } return ret; } PRIVATE int TREEMENU::getskipy() { return (int)GetCharHeight()+6; } /* Compute the height of the visible menu items */ PRIVATE int TREEMENU::getviewlength() { int skipy = getskipy(); int ret = 0; int visible_level = 1; for (int i=0; iSetSize (width,0,20,total_height); //vscroll->SetViewLength(total_height); //vscroll->SetObjectLength(getviewlength()); //vscroll->SetPageLength(200); vscroll->SetScrollbar (0,total_height,getviewlength(),200); } PUBLIC void TREEMENU::dolayout(int, int, bool) { int width = setup(); dispose (width+21,400); } PUBLIC void TREEMENU::resizeitems(int diffx, int diffy) { int w,h; GetClientSize(&w,&h); dispose (w+diffx,h+diffy); } PUBLIC void TREEMENU::getweight(int &w, int &h) { w = 1; h = 1; } PUBLIC TREEMENU::~TREEMENU () { for (int i=0; ilev; j--){ pathlevel[j] = 0; } pathlevel[lev]++; } last_level = lev; { char key[100]; char *ptkey = key; for (int j=1; j<=lev; j++){ ptkey += sprintf (ptkey,"%d/",pathlevel[j]); } tb[i].key = strdup(key); } if (terminal[i]){ pathlevel[lev]++; } } int maxw = 0; int offlev = 2*(int)GetCharWidth(); // Indentation per level for (int i=0; i maxw) maxw = len; } return maxw; } PRIVATE void TREEMENU::drawone (wxDC &dc, int no, int y, bool highlit) { int charh = (int)GetCharHeight(); int skipy = getskipy(); int charw = (int)GetCharWidth(); int skipx = 2*charw; int lev = level[no]; int midy = y + charh/2; const int OFFX = 2; if (no != 0){ // Draw the vertical upper line for (int j=1; j<=lev; j++){ int xc = (j*skipx) - 10 + OFFX; dc.DrawLine (xc,y,xc,midy); } } int x = lev * skipx + OFFX; dc.DrawLine (x-10,midy,x-2,midy); if (no != nbtb-1){ // Draw the vertical lower line int nextlev = level[no+1]; if (nextlev < lev) lev = nextlev; for (int j=1; j<=lev; j++){ int xc = (j*skipx) - 10 + OFFX; dc.DrawLine (xc,midy,xc,y+skipy-1); } } if (!terminal[no]){ int xc = x - 5; dc.SetBrush (*brush_white); dc.DrawRectangle (xc-10,midy-5,10,10); dc.DrawLine (xc-2,midy,xc-8,midy); if (!statopen[no]){ int midx = xc - 10/2; dc.DrawLine (midx,midy-3,midx,midy+3); } } if (highlit){ dc.SetPen (*pen_white); } TREEELM *el = tb + no; if (el->icon != NULL){ dc.DrawBitmap (*el->icon,x,y,TRUE); x += 18; } dc.SetFont (*font_prop); dc.DrawText (el->title,x,y); if (highlit) dc.SetPen (*pen_black); } PRIVATE void TREEMENU::draw (wxDC &dc, int no, bool highlit) { int skipy = getskipy(); int y = -voffset; int visible_level = 1; for (int i=0; i x; bool oncross = event.m_x < x && event.m_x > x - 10; if (onlabel){ report_button (key,false,&event,""); }else if (oncross){ if (statopen[i]){ statopen[i] = false; vscroll->SetObjectLength(getviewlength()); refresh(); }else{ char tmpkey[strlen(key)+2]; tmpkey[0] = '+'; strcpy (tmpkey+1,key); report_button (tmpkey,false,&event,""); } } }else{ statopen[i] = !statopen[i]; vscroll->SetObjectLength(getviewlength()); refresh(); } break; } posy += skipy; } } } } PUBLIC void TREEMENU::dump() { char path[300]; formbase_getabspath(this,path); /* #Specification: tree / preserve the state When a button is depressed, a dump is done of all the sub forms. A TREEMENU will do a dump also. It will output one line per visible node of the tree. Visible nodes include one which are owned by an invisible sub-tree (the sub-tree is collapsed, but the sub-sub-tree is not). Instead of sending the state of each node, we send only the "key" of the visible one. The dump protocol request a field ID and a value. In this case, this is not that appropriate, so we generate pseudo field ID all starting with the letter T. The treemenu module agree with this strategy. So we generate # dump formpath t0 0/0/1 dump formpath t1 2/1/0/1 # The treemenu module will request t0, then t1 until it exhaust the list. */ int id = 0; for (int i=0; i 0){ SetSize (-1,-1,new_width,new_height); if (vscroll != NULL){ vscroll->SetSize (new_width-20,0,-1,-1); } } } #ifndef PROTO_SKIP BEGIN_EVENT_TABLE(TREEMENU, MFORM) EVT_PAINT(TREEMENU::Event_OnPaint) EVT_LEFT_DOWN(TREEMENU::mouseevent) EVT_MIDDLE_DOWN(TREEMENU::mouseevent) EVT_RIGHT_DOWN(TREEMENU::mouseevent) EVT_SCROLL (TREEMENU::vscroll_func) END_EVENT_TABLE() #endif