#include "diawxgtk.h" #include using namespace std; PUBLIC wxTREE::wxTREE ( wxFORMBASE *_parent, const char *_id) : wxTreeCtrl (_parent,-1,wxDefaultPosition,wxSize(400,250) ,wxTR_HAS_BUTTONS|wxTR_HIDE_ROOT), FORMBASE (_parent,_parent,_id) { curlevel=0; tbids[0] = AddRoot ("$$$"); int w = rem_getvarval ("width"); if (w == -1) w=40; int h = rem_getvarval ("height"); if (h == -1) h=20; SetSize (w*10,h*14); } PUBLIC void wxTREE::getweight(int &w, int &h) { w = 1; h = 1; } PUBLIC wxTREE::~wxTREE () { } class TREEDATA: public wxTreeItemData{ public: char *key; TREEDATA(const char *_key){ key = strdup(_key); } ~TREEDATA(){ free (key); } }; /* Store some keys (0/1/2/) in each items of the tree. This is used later when dumping */ PRIVATE void wxTREE::setkeys ( wxTreeItemId parentid, char keypath[], int keylen) { wxTreeItemIdValue cookie; wxTreeItemId id = GetFirstChild(parentid,cookie); int n = 0; while (id.IsOk()){ int len = snprintf (keypath+keylen,5,"%d/",n); SetItemData(id,new TREEDATA(keypath)); setkeys (id,keypath,keylen+len); id = GetNextChild(parentid,cookie); n++; } keypath[keylen] = '\0'; } PRIVATE void wxTREE::setkeys () { char keypath[100]=""; SetItemData(tbids[0],new TREEDATA("")); setkeys (tbids[0],keypath,0); } PRIVATE void wxTREE::setdc (wxTreeItemId &id) { DCNAME *dc = defs_getvardc(); if (dc != NULL){ wxClientDC xdc(this); defs_setdc (dc,xdc); SetItemFont (id,xdc.GetFont()); const wxPen &pen = xdc.GetPen(); SetItemTextColour (id,pen.GetColour()); if (pen.GetWidth() > 1) SetItemBold (id); }else{ #if 0 TREEDATA *data = (TREEDATA*)GetItemData(id); if (data != NULL) fprintf (stderr,"%s Set pas bold\n",data->key); #endif SetItemBold (id,false); SetItemTextColour (id,pen_black->GetColour()); if (IsBold(id)) fprintf (stderr,"Etrange\n"); } } PUBLIC void wxTREE::addelm ( wxBitmap *icon, // Mini icon name const char *title) { wxTreeItemId id; if (curlevel >= 0){ id = AppendItem (tbids[curlevel],title); }else{ id = AddRoot (title); } setdc (id); } PUBLIC void wxTREE::addsub ( bool isopen, wxBitmap *icon, // Mini icon name const char *title) { curlevel++; wxTreeItemId id; if (curlevel == 0){ id = AddRoot (title); }else{ id = AppendItem(tbids[curlevel-1],title); } tbids[curlevel] = id; //fprintf (stderr,"isopen %d %s\n",isopen,title); statopen[curlevel] = isopen; setdc (id); } PUBLIC void wxTREE::endsub () { wxTreeItemId id = tbids[curlevel]; if (!statopen[curlevel]){ Collapse (id); }else{ Expand (id); } curlevel--; } /* We walk the tree to replace, add or delete nodes. Node to be deleted have $del=1. Next nodes are also deleted. The client is using the Setval protocol to change the nodes and always send a Setval with $del=1 to ask us to "cut" the end of a branch, even if there is more nodes or not. */ PRIVATE bool wxTREE::set_add ( wxTreeItemId &parentid, const char *key, int lenkey, const char *items[]) { bool ret = false; TREEDATA *data = (TREEDATA*)GetItemData(parentid); int lendata = strlen(data->key); if (strncmp(key,data->key,lendata)==0){ // We are entering the proper branch //fprintf (stderr,"match :%s: :%s:\n",key,data->key); bool dodel = rem_getvarval ("del")==1; bool expanded = atoi(items[0])==1; wxTreeItemIdValue cookie; wxTreeItemId id = GetFirstChild(parentid,cookie); list todel; bool deleting = false; while (id.IsOk()){ TREEDATA *data = (TREEDATA*)GetItemData(id); if (strcmp(data->key,key)==0){ if (dodel){ deleting = true; todel.push_back(id); }else{ const char *oldtext = GetItemText(id); if (strcmp(oldtext,items[2])!=0){ SetItemText (id,items[2]); } bool state = IsExpanded(id); // fprintf (stderr,"update key %s %s<>%s %d<>%d\n",key,items[2],oldtext,expanded,state); if (state != expanded){ if (expanded){ Expand (id); }else{ Collapse (id); } } setdc (id); } ret = true; }else if (deleting){ todel.push_back(id); }else{ ret |= set_add (id,key,lenkey,items); if (ret) break; } id = GetNextChild(parentid,cookie); } if (!ret && !dodel){ // We are in the proper branch, but did not find the leaf // so we must add it here ret = true; id = AppendItem(parentid,items[2]); SetItemData(id,new TREEDATA(key)); }else if (todel.size()>0){ typedef list::iterator listit; for (listit it=todel.begin(); it != todel.end(); it++){ DeleteChildren(*it); Delete(*it); } } } return ret; } PUBLIC void wxTREE::Set_item( const char *id, const char *vals[]) { setkeys(); // fprintf (stderr,"set_item :%s: :%s: :%s: :%s:\n",id,vals[0],vals[1],vals[2]); set_add (tbids[0],id,strlen(id),vals); } PUBLIC void wxTREE::mouseevent(wxMouseEvent & event) { setkeys(); wxPoint pt(event.m_x,event.m_y); int flags = 0; wxTreeItemId id = HitTest (pt,flags); if (id.IsOk()){ if (flags & wxTREE_HITTEST_ONITEMLABEL){ Unselect(); SelectItem (id); TREEDATA *data = (TREEDATA*)GetItemData(id); char path[300]; formbase_getabspath(this,path); remadmin_setcursor (cursor_wait); int bstate = mform_mev2state(event); int x=event.m_x,y=event.m_y; ClientToScreen(&x,&y); dump(); y -= 45; // cheaty ???? rem_setlastmouse (x,y); fprintf (mform_fout,"action %s %s %d %d %d\n",path,data->key,bstate,x,y); fflush (mform_fout); }else if (flags & wxTREE_HITTEST_ONITEMBUTTON){ bool state = IsExpanded(id); if (state){ Collapse(id); }else{ Expand (id); } } } } PRIVATE void wxTREE::dump ( wxTreeItemId &parentid, const char *path, int &ref) { wxTreeItemIdValue cookie; wxTreeItemId id = GetFirstChild(parentid,cookie); int n = 0; while (id.IsOk()){ if (IsExpanded(id)){ TREEDATA *data = (TREEDATA*)GetItemData(id); fprintf (mform_fout,"dump %s t%d %s\n",path,ref++,data->key); } dump (id,path,ref); id = GetNextChild(parentid,cookie); n++; } } PUBLIC void wxTREE::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 wxTREE 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 ref=0; dump (tbids[0],path,ref); } #ifndef PROTO_SKIP BEGIN_EVENT_TABLE(wxTREE, wxTreeCtrl) EVT_LEFT_DOWN(wxTREE::mouseevent) EVT_MIDDLE_DOWN(wxTREE::mouseevent) EVT_RIGHT_DOWN(wxTREE::mouseevent) END_EVENT_TABLE() #endif