#include "wxinc.h" #define XTWIN_CPP 1 #include "xvt.h" #include "xvtwin.h" #include "wx/image.h" #include "wx/notebook.h" #include "wx/treectrl.h" #if wxCHECK_VERSION(2,8,7) #include "wx/aui/aui.h" #endif /////////////////////////////////////////////////////////// // Utilities /////////////////////////////////////////////////////////// wxHashTable _nice_windows; wxWindow* _task_win = NULL; EVENT_HANDLER _task_win_handler = NULL; wxRect NormalizeRCT(const RCT* prct) { wxRect rct; if (prct != NULL) { rct.x = min(prct->left, prct->right); rct.y = min(prct->top, prct->bottom); rct.width = abs(prct->right - prct->left); rct.height = abs(prct->bottom - prct->top); } return rct; } /////////////////////////////////////////////////////////// // Caret emulation /////////////////////////////////////////////////////////// class TwxCaret : private wxTimer { WINDOW _owner; PNT _pos; wxSize _size; bool _visible; bool _drawn; protected: void Toggle(); virtual void Notify() { Toggle(); } public: void SetPos(int x, int y); void SetSize(int x, int y) { _size.x = x; _size.y = y; } void Show(WINDOW w, bool on = true); void Hide() { Show(NULL_WIN, false); } bool IsVisible() const { return _visible; } WINDOW Owner() const { return _owner; } void Kill(); TwxCaret() : _owner(NULL_WIN), _visible(false) { } virtual ~TwxCaret() { Kill(); } } _TheCaret; void TwxCaret::Kill() { _owner = NULL_WIN; } void TwxCaret::SetPos(int x, int y) { if (_visible && _drawn) // Lo cancella se necessario Toggle(); _pos.h = x; _pos.v = y; } void TwxCaret::Show(WINDOW w, bool on) { if (_visible && _drawn) Toggle(); // Lo cancella _visible = on; if (on) { _owner = w; Toggle(); wxTimer::Start(500); // Lampeggia ogni mezzo secondo } else { if (w == _owner || w == NULL_WIN) Kill(); } } void TwxCaret::Toggle() { if (!_visible || _owner == NULL_WIN) return; _drawn = !_drawn; DRAW_CTOOLS dct; xvt_dwin_get_draw_ctools(_owner, &dct); CPEN pen; pen.width = _size.x; pen.pat = PAT_SOLID; pen.style = P_SOLID; pen.color = dct.fore_color; xvt_dwin_set_draw_mode(_owner, M_NOT_XOR); xvt_dwin_set_cpen(_owner, &pen); xvt_dwin_draw_set_pos(_owner, _pos); PNT p = _pos; p.v -= _size.y-1; xvt_dwin_set_clip(_owner, NULL); // Non si sa mai! xvt_dwin_draw_line(_owner, p); xvt_dwin_set_draw_ctools(_owner, &dct); } void xvt_win_set_caret_size(WINDOW win, int width, int height) { _TheCaret.SetSize(width, height); } void xvt_win_set_caret_pos(WINDOW win, PNT p) { _TheCaret.SetPos(p.h, p.v-1); } void xvt_win_set_caret_visible(WINDOW win, BOOLEAN on) { _TheCaret.Show(win, on != 0); } /////////////////////////////////////////////////////////// // Generic Display context /////////////////////////////////////////////////////////// TDC::TDC(wxWindow* owner) : _dc(NULL) { _owner = owner; memset(&_dct, 0, sizeof(_dct)); _dct.pen.width = 0; _dct.pen.pat = PAT_SOLID; _dct.pen.style = P_SOLID; _dct.pen.color = COLOR_BLACK; _dct.brush.pat = PAT_HOLLOW; _dct.brush.color = COLOR_WHITE; _dct.mode = M_COPY; _dct.fore_color = COLOR_BLACK; _dct.back_color = COLOR_WHITE; _dct.opaque_text = FALSE; _font.SetPointSize(9); // Default font _deltaf = 0; // Reset clip area SetClippingBox(NULL); _real_clip = _clip; _dirty = -1; // Absolutely force setting } TDC::~TDC() { KillDC(); } void TDC::SetDirty(int d) { if (_dirty >= 0) _dirty = d; } static int PatternToStyle(PAT_STYLE pat) { int style = wxSOLID; switch (pat) { case PAT_NONE: case PAT_HOLLOW: style = wxTRANSPARENT; break; case PAT_SOLID: style = wxSOLID; break; case PAT_HORZ: style = wxHORIZONTAL_HATCH; break; case PAT_VERT: style = wxVERTICAL_HATCH; break; case PAT_FDIAG: style = wxFDIAGONAL_HATCH; break; case PAT_BDIAG: style = wxBDIAGONAL_HATCH; break; case PAT_CROSS: style = wxCROSS_HATCH; break; case PAT_DIAGCROSS: style = wxCROSSDIAG_HATCH; break; case PAT_RUBBER: case PAT_SPECIAL: default: SORRY_BOX(); break; } return style; } static int PenStyleToStyle(PEN_STYLE s, PAT_STYLE p) { int style = wxSOLID; if (p != PAT_HOLLOW) { switch (s) { case P_DOT : style = wxDOT; break; case P_DASH: style = wxSHORT_DASH; break; default: break; } } else style = wxTRANSPARENT; return style; } bool TDC::PenChanged() const { const int diff = memcmp(&_dct.pen, &_real_dct.pen, sizeof(_dct.pen)); return diff != 0; } bool TDC::BrushChanged() const { const int diff = memcmp(&_dct.brush, &_real_dct.brush, sizeof(_dct.brush)); return diff != 0; } bool TDC::FontChanged() const { return _font != _real_font; } bool TDC::ClipChanged() const { const int diff = memcmp(&_clip, &_real_clip, sizeof(_clip)); return diff != 0; } #ifdef LINUX bool is_printer_dc(wxDC * dc) { return dc->IsKindOf(CLASSINFO(wxPostScriptDC)); } #endif wxDC& TDC::GetDC(bool bPaint) { if (bPaint) { KillDC(); _dc = new wxPaintDC(_owner); _dirty = -1; } else { if (_dc == NULL) { if (_owner == NULL || (unsigned long)_owner == SCREEN_WIN) _dc = new wxScreenDC(); else _dc = new wxClientDC(_owner); _dirty = -1; } } if (_dirty) { if (_dirty < 0 || PenChanged()) { CAST_COLOR(_dct.pen.color, pen_color); wxPen* pen = wxThePenList->FindOrCreatePen(pen_color, _dct.pen.width, PenStyleToStyle(_dct.pen.style, _dct.pen.pat)); _dc->SetPen(*pen); _real_dct.pen = _dct.pen; } if (_dirty < 0 || BrushChanged()) { CAST_COLOR(_dct.brush.color, brush_color); wxBrush* brush = wxTheBrushList->FindOrCreateBrush(brush_color, PatternToStyle(_dct.brush.pat)); _dc->SetBrush(*brush); _real_dct.brush = _dct.brush; } if (_dirty < 0 || _dct.mode != _real_dct.mode) { #ifdef LINUX if(!is_printer_dc(_dc)) { #endif switch(_dct.mode) { case M_COPY: _dc->SetLogicalFunction(wxCOPY); break; case M_OR: _dc->SetLogicalFunction(wxOR); break; case M_XOR: _dc->SetLogicalFunction(wxXOR); break; case M_CLEAR: _dc->SetLogicalFunction(wxCLEAR); break; case M_NOT_COPY: _dc->SetLogicalFunction(wxSRC_INVERT); break; case M_NOT_OR: _dc->SetLogicalFunction(wxNOR); break; case M_NOT_XOR: _dc->SetLogicalFunction(wxEQUIV); break; case M_NOT_CLEAR:_dc->SetLogicalFunction(wxSET); break; default: SORRY_BOX(); } #ifdef LINUX } #endif _real_dct.mode = _dct.mode; } if (_dirty < 0 || _dct.fore_color != _real_dct.fore_color) { CAST_COLOR(_dct.fore_color, fore_color); _dc->SetTextForeground(fore_color); _real_dct.fore_color = _dct.fore_color; } if (_dirty < 0 || _dct.back_color != _real_dct.back_color) { CAST_COLOR(_dct.back_color, back_color); _dc->SetTextBackground(back_color); _real_dct.back_color = _dct.back_color; } if (_dirty < 0 || _dct.opaque_text != _real_dct.opaque_text) { _dc->SetBackgroundMode(_dct.opaque_text ? wxSOLID : wxTRANSPARENT); _real_dct.opaque_text = _dct.opaque_text; } if (_dirty < 0 || FontChanged()) { const wxFont& f = _font.Font(_dc, (WINDOW)_owner); _dc->SetFont(f); _real_font = _font; int height, desc, lead; _dc->GetTextExtent("Campo", NULL, &height, &desc, &lead); _deltaf = height-desc; } if (_dirty < 0 || ClipChanged()) { _dc->DestroyClippingRegion(); if (_clip.bottom < 4096) _dc->SetClippingRegion(NormalizeRCT(&_clip)); _real_clip = _clip; } _dirty = false; } return *_dc; } void TDC::KillDC() { if (_dc != NULL) { SetClippingBox(NULL); _real_clip = _clip; delete _dc; _dc = NULL; } } void TDC::SetClippingBox(const RCT* pRct) { if (pRct != NULL) { const wxRect rct = NormalizeRCT(pRct); _clip.left = rct.x; _clip.top = rct.y; _clip.right = rct.GetRight(); _clip.bottom = rct.GetBottom(); } else { _clip.left = _clip.top = 0; _clip.right = _clip.bottom = 4096; } } bool TDC::GetClippingBox(RCT* pRct) const { *pRct = _clip; return _clip.right > _clip.left; } TDCMapper& GetTDCMapper() { static TDCMapper* _dc_map = NULL; if (_dc_map == NULL) _dc_map = new TDCMapper; return *_dc_map; } void TDCMapper::DestroyDC(WINDOW owner) { if (owner) { TDC* pTDC = (*this)[owner]; if (pTDC) pTDC->KillDC(); } else { for (TDCMapper::iterator it = begin(); it != end(); ++it) { TDC* pTDC = it->second; if (pTDC) pTDC->KillDC(); } } } void TDCMapper::DestroyTDC(WINDOW owner) { if (owner != NULL_WIN) { TDC* pTDC = (*this)[owner]; if (pTDC) delete pTDC; erase(owner); } else { TDCMapper::iterator it; for (it = begin(); it != end(); ++it) { TDC* pTDC = it->second; if (pTDC) delete pTDC; } clear(); } _pLastOwner = NULL_WIN; } TDC& TDCMapper::GetTDC(WINDOW owner) { if (owner != _pLastOwner) { TDC* pTDC = (*this)[owner]; if (pTDC == NULL) { if (owner == PRINTER_WIN) pTDC = new TPrintDC((wxWindow*)owner); else pTDC = new TDC((wxWindow*)owner); (*this)[owner] = pTDC; } _pLastOwner = owner; _pLastTDC = pTDC; } return *_pLastTDC; } bool TDCMapper::HasValidDC(WINDOW owner) const { if (owner == NULL_WIN) return false; if (owner == (WINDOW)_pLastOwner) return true; TDC* pTDC = (*((TDCMapper *) this))[owner]; return pTDC != NULL; } /////////////////////////////////////////////////////////// // Generic window class /////////////////////////////////////////////////////////// IMPLEMENT_DYNAMIC_CLASS(TwxWindowBase, wxWindow) bool TwxWindowBase::CreateBase(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style) { // Evita inutili sfarfallamenti in quanto wxWidgets crea le finestre visibili per default wxWindowBase::Show(false); bool ok = Create(parent, id, pos, size, style, title); if (ok) { #if wxCHECK_VERSION(2,8,7) #else SetTitle(title); // Triste necessita', la Create sembra ignorare il titolo #endif } return ok; } TwxWindowBase::TwxWindowBase(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style) { CreateBase(parent, id, title, pos, size, style); } IMPLEMENT_DYNAMIC_CLASS(TwxWindow, TwxWindowBase) BEGIN_EVENT_TABLE(TwxWindow, TwxWindowBase) EVT_CHAR(TwxWindow::OnChar) EVT_KEY_DOWN(TwxWindow::OnKeyDown) EVT_CLOSE(TwxWindow::OnClose) EVT_KILL_FOCUS(TwxWindow::OnKillFocus) EVT_LEFT_DCLICK(TwxWindow::OnMouseDouble) EVT_LEFT_DOWN(TwxWindow::OnMouseDown) EVT_LEFT_UP(TwxWindow::OnMouseUp) EVT_MENU_RANGE(1000, 32766, TwxWindow::OnMenu) EVT_MIDDLE_DOWN(TwxWindow::OnMouseDown) EVT_MIDDLE_UP(TwxWindow::OnMouseUp) EVT_MOTION(TwxWindow::OnMouseMove) #if wxCHECK_VERSION(2,8,7) EVT_MOUSE_CAPTURE_LOST(TwxWindow::OnMouseCaptureLost) #endif EVT_MOUSEWHEEL(TwxWindow::OnMouseWheel) EVT_PAINT(TwxWindow::OnPaint) EVT_RIGHT_DOWN(TwxWindow::OnMouseDown) EVT_RIGHT_UP(TwxWindow::OnMouseUp) EVT_SCROLL(TwxWindow::OnScroll) EVT_SCROLLWIN(TwxWindow::OnScrollWin) EVT_SET_FOCUS(TwxWindow::OnSetFocus) EVT_SIZE(TwxWindow::OnSize) EVT_TIMER(TIMER_ID, TwxWindow::OnTimer) EVT_COMMAND_RANGE(1, 9999, wxEVT_COMMAND_BUTTON_CLICKED, TwxWindow::OnButton) EVT_COMMAND_RANGE(1, 9999, wxEVT_COMMAND_CHECKBOX_CLICKED, TwxWindow::OnCheckBox) EVT_COMMAND_RANGE(1, 9999, wxEVT_COMMAND_RADIOBUTTON_SELECTED, TwxWindow::OnRadioButton) END_EVENT_TABLE() void TwxWindow::DoXvtEvent(EVENT& e) { if (this != NULL && _eh != NULL) _eh((WINDOW)this, &e); } void TwxWindow::OnChar(wxKeyEvent& evt) { static int nSkipNextDotKey = -883; // Valore indefinito if (nSkipNextDotKey == -883) // Devo stabilire se attivare la gestione o no { const char* campoini = xvt_fsys_get_campo_ini(); char str[2]; xvt_sys_get_profile_string(campoini, "Main", "Point2Comma", "1", str, sizeof(str)); nSkipNextDotKey = strchr("1XY", *str) != NULL ? 0 : -1; // Dis/Abilita conversione punto in virgola } EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CHAR; int k = evt.GetKeyCode(); if (nSkipNextDotKey == 1) { nSkipNextDotKey = 0; if (k == '.') { evt.Skip(); return; } } switch (k) { case WXK_ALT: case WXK_MENU: case WXK_NUMPAD0: case WXK_NUMPAD1: case WXK_NUMPAD2: case WXK_NUMPAD3: case WXK_NUMPAD4: case WXK_NUMPAD5: case WXK_NUMPAD6: case WXK_NUMPAD7: case WXK_NUMPAD8: case WXK_NUMPAD9: evt.Skip(); return; case WXK_NUMPAD_DECIMAL: // Arriva solo dalla 3.6.3 in poi case WXK_DECIMAL: // ??? Arriva sia '.' sia WXK_DECIMAL=340 if (nSkipNextDotKey == 0) { k = ','; // Trasformo il punto in virgola nSkipNextDotKey = 1; } break; case WXK_NUMPAD_ADD: k = '+';break; case WXK_DOWN : k = K_DOWN; break; case WXK_END : k = K_LEND; break; case WXK_HOME : k = K_LHOME; break; case WXK_LEFT : k = K_LEFT; break; case WXK_NEXT : k = K_NEXT; break; case WXK_PRIOR: k = K_PREV; break; case WXK_RIGHT: k = K_RIGHT; break; case WXK_UP : k = K_UP; break; case WXK_TAB: if (evt.ShiftDown()) k = K_BTAB; break; default: if (k >= WXK_F1 && k <= WXK_F24) k = K_F1 + k - WXK_F1; break; } e.v.chr.shift = evt.ShiftDown(); e.v.chr.control = evt.ControlDown(); if (evt.AltDown()) { e.v.chr.control = TRUE; if (xvt_chr_is_alnum(k)) k = toupper(k); else { if (strchr("+-", k) == NULL) // Aggiungere qui vari testi eventuali { evt.Skip(); return; } } } e.v.chr.ch = k; DoXvtEvent(e); } void TwxWindow::OnKeyDown(wxKeyEvent& e) { #ifdef WIN32 // Triste necessita' per gestire corretamente Alt+'+' del tasterino const int k = e.GetKeyCode(); if (k == WXK_NUMPAD_ADD) { if (e.AltDown()) { OnChar(e); return; } } #else if (e.AltDown() || e.ControlDown()) { OnChar(event); return; } #endif e.Skip(); } void TwxWindow::OnClose(wxCloseEvent& WXUNUSED(e)) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_DESTROY; DoXvtEvent(e); Destroy(); } void TwxWindow::OnKillFocus(wxFocusEvent& WXUNUSED(e)) { if (_TheCaret.Owner() == (WINDOW)this) _TheCaret.Hide(); EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_FOCUS; e.v.active = 0; DoXvtEvent(e); } void TwxWindow::OnMenu(wxCommandEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_COMMAND; e.v.cmd.control = 0; e.v.cmd.shift = 0; e.v.cmd.tag = evt.GetId(); DoXvtEvent(e); } #if wxCHECK_VERSION(2,8,7) void TwxWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(e)) { xvt_win_release_pointer(); } #endif void TwxWindow::OnMouseDouble(wxMouseEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_MOUSE_DBL; e.v.mouse.button = (evt.RightDown() ? 1 : 0) + (evt.MiddleDown() ? 2 : 0); e.v.mouse.control = evt.ControlDown(); e.v.mouse.shift = evt.ShiftDown(); e.v.mouse.where.h = evt.GetX(); e.v.mouse.where.v = evt.GetY(); DoXvtEvent(e); } void TwxWindow::OnMouseDown(wxMouseEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_MOUSE_DOWN; e.v.mouse.button = (evt.RightDown() ? 1 : 0) + (evt.MiddleDown() ? 2 : 0); e.v.mouse.control = evt.ControlDown(); e.v.mouse.shift = evt.ShiftDown(); e.v.mouse.where.h = evt.GetX(); e.v.mouse.where.v = evt.GetY(); DoXvtEvent(e); SetFocus(); // Triste necessita' } void TwxWindow::OnMouseMove(wxMouseEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_MOUSE_MOVE; e.v.mouse.button = (evt.RightIsDown() ? 1 : 0) + (evt.MiddleIsDown() ? 2 : 0); e.v.mouse.control = evt.ControlDown(); e.v.mouse.shift = evt.m_shiftDown; e.v.mouse.where.h = evt.GetX(); e.v.mouse.where.v = evt.GetY(); DoXvtEvent(e); } void TwxWindow::OnMouseUp(wxMouseEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_MOUSE_UP; e.v.mouse.button = (evt.RightUp() ? 1 : 0) + (evt.MiddleUp() ? 2 : 0); e.v.mouse.control = evt.ControlDown(); e.v.mouse.shift = evt.ShiftDown(); e.v.mouse.where.h = evt.GetX(); e.v.mouse.where.v = evt.GetY(); DoXvtEvent(e); } void TwxWindow::OnMouseWheel(wxMouseEvent& evt) { const int nRot = evt.GetWheelRotation(); if (nRot != 0) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_VSCROLL; e.v.scroll.pos = evt.GetY(); e.v.scroll.what = nRot > 0 ? SC_LINE_UP : SC_LINE_DOWN; DoXvtEvent(e); } } void TwxWindow::OnPaint(wxPaintEvent& WXUNUSED(evt)) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_UPDATE; RCT& rct = e.v.update.rct; wxRect rctDamaged = GetUpdateRegion().GetBox(); rct.left = rctDamaged.x; rct.top = rctDamaged.y; rct.right = rctDamaged.GetRight()+1; rct.bottom = rctDamaged.GetBottom()+1; TDC& tdc = GetTDCMapper().GetTDC((WINDOW)this); tdc.GetDC(true); // Forza la creazione di un wxPaintDC DoXvtEvent(e); tdc.KillDC(); // Distrugge il wxPaintDC GetTDCMapper().DestroyDC(NULL_WIN); // Distrugge davvero tutti i wxClientDC residui (risolve molte "porcate" del video) } static SCROLL_CONTROL ConvertScrollToXVT(wxEventType et) { if (et == wxEVT_SCROLL_TOP) return SC_THUMB; // Meglio di niente if (et == wxEVT_SCROLL_BOTTOM) return SC_THUMB; // Meglio di niente if (et == wxEVT_SCROLL_LINEUP) return SC_LINE_UP; if (et == wxEVT_SCROLL_LINEDOWN) return SC_LINE_DOWN; if (et == wxEVT_SCROLL_PAGEUP) return SC_PAGE_UP; if (et == wxEVT_SCROLL_PAGEDOWN) return SC_PAGE_DOWN; if (et == wxEVT_SCROLL_THUMBTRACK) return SC_THUMBTRACK; if (et == wxEVT_SCROLL_THUMBRELEASE) return SC_THUMB; return SC_NONE; } void TwxWindow::OnScroll(wxScrollEvent& evt) { SCROLL_CONTROL sc = ConvertScrollToXVT(evt.GetEventType()); if (sc != SC_NONE) { const wxScrollBar* sb = (wxScrollBar*)evt.GetEventObject(); const wxSize sz = sb->GetSize(); EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = sz.x > sz.y ? WC_HSCROLL : WC_VSCROLL; e.v.ctl.ci.win = (WINDOW)sb; e.v.ctl.ci.v.scroll.pos = evt.GetPosition(); e.v.ctl.ci.v.scroll.what = sc; DoXvtEvent(e); } } void TwxWindow::OnScrollWin(wxScrollWinEvent& evt) { wxEventType et = evt.GetEventType(); et -= (wxEVT_SCROLLWIN_TOP - wxEVT_SCROLL_TOP); const SCROLL_CONTROL sc = ConvertScrollToXVT(et); if (sc != SC_NONE) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = evt.GetOrientation() == wxHORIZONTAL ? E_HSCROLL : E_VSCROLL; e.v.scroll.pos = evt.GetPosition(); e.v.scroll.what = sc; DoXvtEvent(e); } } void TwxWindow::OnSetFocus(wxFocusEvent& WXUNUSED(e)) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_FOCUS; e.v.active = 1; DoXvtEvent(e); } void TwxWindow::OnSize(wxSizeEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_SIZE; e.v.size.width = evt.GetSize().x; e.v.size.height = evt.GetSize().y; DoXvtEvent(e); } void TwxWindow::OnTimer(wxTimerEvent& WXUNUSED(evt)) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_TIMER; e.v.timer.id = (WINDOW)this; DoXvtEvent(e); } void TwxWindow::OnButton(wxCommandEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_PUSHBUTTON; DoXvtEvent(e); } void TwxWindow::OnCheckBox(wxCommandEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_CHECKBOX; DoXvtEvent(e); } void TwxWindow::OnRadioButton(wxCommandEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_RADIOBUTTON; DoXvtEvent(e); } void TwxWindow::SetMenuTree(const MENU_ITEM* tree) { wxASSERT(tree != NULL); if (tree != NULL) { if (m_menu) xvt_res_free_menu_tree(m_menu); m_menu = xvt_menu_duplicate_tree(tree); ((TTaskWin*)_task_win)->PushMenuTree(tree, this); } } BOOLEAN TwxWindow::AddPane(wxWindow* wnd, const char* caption, int nDock, int nFlags) { BOOLEAN ok = wnd != NULL; #if wxCHECK_VERSION(2,8,7) if (ok) { if (m_pManager == NULL) m_pManager = new wxAuiManager(this); wxAuiPaneInfo pane; pane.DefaultPane(); pane.Dockable(false); if (caption && *caption) pane.Caption(caption); const wxSize sz = wnd->GetSize(); switch (nDock) { case 1: pane.Left().LeftDockable().RightDockable().MinSize(sz.x/2, -1); break; case 2: pane.Top().TopDockable().BottomDockable().MinSize(-1, sz.y/2); break; case 3: pane.Right().LeftDockable().RightDockable().MinSize(sz.x/2, -1); break; case 4: pane.Bottom().TopDockable().BottomDockable().MinSize(-1, sz.y/2); break; default: pane.CentrePane().Floatable(false); break; } ok = m_pManager->AddPane(wnd, pane); if (ok) m_pManager->Update(); } #endif return ok; } TwxWindow::TwxWindow() : m_menu(NULL), _type(W_DOC), _eh(NULL), _app_data(0L), _timer(NULL), m_pManager(NULL) { } TwxWindow::TwxWindow(wxWindow *parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : TwxWindowBase(parent, id, title, pos, size, style), m_menu(NULL), _eh(NULL), _timer(NULL), m_pManager(NULL) { _nice_windows.Put((WINDOW)this, this); } TwxWindow::~TwxWindow() { if (_timer) delete _timer; #if wxCHECK_VERSION(2,8,7) if (m_pManager) { m_pManager->UnInit(); // Obbligatorio ma, chissa' perche', non gestito dal distruttore! delete m_pManager; } #endif if (m_menu) { xvt_res_free_menu_tree(m_menu); ((TTaskWin*)_task_win)->PopMenuTree(); } _nice_windows.Delete((WINDOW)this); } /////////////////////////////////////////////////////////// // Main application = TASK_WIN functions /////////////////////////////////////////////////////////// IMPLEMENT_DYNAMIC_CLASS(TTaskWin, wxFrame) BEGIN_EVENT_TABLE(TTaskWin, wxFrame) EVT_CLOSE(TTaskWin::OnClose) EVT_MENU_RANGE(1000, 32766, TTaskWin::OnMenu) EVT_PAINT(TTaskWin::OnPaint) EVT_SIZE(TTaskWin::OnSize) END_EVENT_TABLE() void TTaskWin::OnClose(wxCloseEvent& evt) { if (evt.CanVeto()) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CLOSE; int veto = _task_win_handler((WINDOW)this, &e); evt.Veto(veto != 0); } else evt.Skip(); } void TTaskWin::OnMenu(wxCommandEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_COMMAND; e.v.cmd.control = 0; e.v.cmd.shift = 0; e.v.cmd.tag = evt.GetId(); if (m_MenuOwner == NULL || m_MenuOwner == this) _task_win_handler((WINDOW)this, &e); else ((TwxWindow*)m_MenuOwner)->_eh((WINDOW)m_MenuOwner, &e); } void TTaskWin::OnPaint(wxPaintEvent& WXUNUSED(evt)) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_UPDATE; RCT& rct = e.v.update.rct; wxRect rctDamaged = GetUpdateRegion().GetBox(); rct.left = rctDamaged.x; rct.top = rctDamaged.y; rct.right = rctDamaged.GetRight()+1; rct.bottom = rctDamaged.GetBottom()+1; TDC& dc = GetTDCMapper().GetTDC((WINDOW)this); dc.GetDC(true); // Forza la creazione di un wxPaintDC _task_win_handler((WINDOW)this, &e); dc.KillDC(); } void TTaskWin::OnSize(wxSizeEvent& evt) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_SIZE; e.v.size.width = evt.GetSize().x; e.v.size.height = evt.GetSize().y; _task_win_handler((WINDOW)this, &e); } void TTaskWin::SetMenuTree(const MENU_ITEM* tree) { if (m_menu) xvt_res_free_menu_tree(m_menu); m_menu = xvt_menu_duplicate_tree(tree); wxMenuBar* bar = GetMenuBar(); for ( ; tree != NULL && tree->tag != 0; tree++) { wxMenu* pMenu = new wxMenu; for (MENU_ITEM* mi = tree->child; mi != NULL && mi->tag != 0; mi++) { wxMenuItem* item = NULL; if (mi->separator) item = new wxMenuItem(pMenu, wxID_SEPARATOR); else item = new wxMenuItem(pMenu, mi->tag, mi->text, wxEmptyString, mi->checkable); pMenu->Append(item); } const int nLast = bar->GetMenuCount()-1; int m; for (m = 2; m < nLast; m++) { wxMenu* pMenu = bar->GetMenu(m); if (pMenu->FindItem(tree->child->tag)) { bar->Remove(m); // delete pMenu; break; } } bar->Insert(m, pMenu, tree->text); } } void TTaskWin::PushMenuTree(const MENU_ITEM* tree, wxWindow* owner) { if(m_pOldBar != NULL) PopMenuTree(); m_pOldBar = GetMenuBar(); wxMenuBar* pBar = new wxMenuBar; for (; tree && tree->tag != 0; tree++) { wxMenu* pMenu = new wxMenu; for (MENU_ITEM* mi = tree->child; mi != NULL && mi->tag != 0; mi++) { wxMenuItem* item = NULL; if (mi->separator) item = new wxMenuItem(pMenu, wxID_SEPARATOR); else item = new wxMenuItem(pMenu, mi->tag, mi->text, wxEmptyString, mi->checkable); pMenu->Append(item); } pBar->Append(pMenu, tree->text); } SetMenuBar(pBar); m_MenuOwner = owner; } void TTaskWin::PopMenuTree() { wxASSERT(m_pOldBar != NULL); wxMenuBar* pBar = GetMenuBar(); SetMenuBar(m_pOldBar); delete pBar; m_pOldBar = NULL; m_MenuOwner = NULL; // = this; } TTaskWin::TTaskWin(wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(NULL, id, title, pos, size, style), m_menu(NULL), m_pOldBar(NULL), m_MenuOwner(NULL) { wxIcon* ico = _GetIconResource(ICON_RSRC); if (ico) SetIcon(*ico); _nice_windows.Put((WINDOW)this, this); } TTaskWin::~TTaskWin() { if (m_menu) { xvt_res_free_menu_tree(m_menu); m_menu = NULL; } _nice_windows.Delete((WINDOW)this); } /////////////////////////////////////////////////////////// // Controls functions /////////////////////////////////////////////////////////// class TwxScrollBar : public wxScrollBar { protected: virtual bool AcceptsFocus() const { return false; } // Altrimenti mette il flag wxTAB_TRAVERSAL public: TwxScrollBar(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) { Create(parent, id, pos, size, style); } }; class TwxNoteBook : public wxNotebook { public: wxNotebookPage* AddTab(int idx, const wxString text, wxBitmap* bmp); TwxNoteBook(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size); }; class TwxTreeCtrl : public wxTreeCtrl { #if wxCHECK_VERSION(2,8,7) WX_DECLARE_VOIDPTR_HASH_MAP(int, XVT_IMAGE_Map); XVT_IMAGE_Map m_img; #else wxHashTable m_img; #endif wxFont m_font; int m_nFrozen; private: int img2int(XVT_IMAGE img); // Store img into internal image list void OnClick(wxTreeEvent& evt, bool bDouble); protected: DECLARE_EVENT_TABLE(); void OnExpanding(wxTreeEvent& e); // Called when node in about to be expanded void OnCollapsed(wxTreeEvent& e); // Called when node is collapsed void OnSelected(wxTreeEvent& e); // Calls OnClick(e, false) void OnActivated(wxTreeEvent& e); // Calls OnClick(e, true) public: void SetNodeImages(const wxTreeItemId& id, XVT_IMAGE item_image, XVT_IMAGE collapsed_image, XVT_IMAGE expanded_image); #if wxCHECK_VERSION(2,8,7) virtual bool SetFont(const wxFont& font) { m_font = font; return font.IsOk(); } #else virtual bool SetFont(const wxFont& font) { m_font = font; return true; } #endif virtual wxFont GetFont() const; void Suspend(); void Resume(); TwxTreeCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size); }; WINDOW xvt_ctl_create_def(WIN_DEF *win_def_p, WINDOW parent_win, long app_data) { wxASSERT(win_def_p != NULL); const wxRect rct = NormalizeRCT(&win_def_p->rct); wxWindow* pParent = (wxWindow*)parent_win; const wxWindowID id = win_def_p->v.ctl.ctrl_id; WINDOW win = NULL_WIN; switch (win_def_p->wtype) { case WC_HSCROLL: /* horizontal scrollbar control */ case WC_VSCROLL: /* vertical scrollbar control */ { const long style = win_def_p->wtype == WC_HSCROLL ? wxSB_HORIZONTAL : wxSB_VERTICAL; TwxScrollBar* sb = new TwxScrollBar(pParent, id, rct.GetPosition(), rct.GetSize(), style); win = (WINDOW)sb; } break; case WC_HGAUGE: /* horizontal progress bar control */ case WC_VGAUGE: /* vertical progress bar control */ { const long style = (win_def_p->wtype == WC_HGAUGE) ? wxGA_HORIZONTAL : wxGA_VERTICAL; wxGauge* pg = new wxGauge(pParent, id, app_data, rct.GetPosition(), rct.GetSize(), style); win = (WINDOW)pg; } break; case WC_PUSHBUTTON: /* bottone normale */ { wxButton* pb = NULL; if (win_def_p->text && *win_def_p->text) // Bottone normale con label { pb = new wxButton(pParent, id, win_def_p->text, rct.GetPosition(), rct.GetSize()); } else { // Bottone figo con immagini wxBitmap bmp; pb = new wxBitmapButton(pParent, id, bmp, rct.GetPosition(), rct.GetSize()); } win = (WINDOW)pb; } break; case WC_CHECKBOX: /* check box */ { long style = wxCHK_2STATE | wxTRANSPARENT_WINDOW; if (win_def_p->wtype == CTL_FLAG_RIGHT_JUST) style |= wxALIGN_RIGHT; wxCheckBox* cb = new wxCheckBox(pParent, id, win_def_p->text, rct.GetPosition(), rct.GetSize(), style); win = (WINDOW)cb; } break; case WC_RADIOBUTTON: /* radio button */ { wxRadioButton* rb = new wxRadioButton(pParent, id, win_def_p->text, rct.GetPosition(), rct.GetSize()); win = (WINDOW)rb; } break; case WC_NOTEBK: { TwxNoteBook* nb = new TwxNoteBook(pParent, id, rct.GetPosition(), rct.GetSize()); win = (WINDOW)nb; } break; case WC_TREE: { TwxTreeCtrl* tv = new TwxTreeCtrl(pParent, id, rct.GetPosition(), rct.GetSize()); win = (WINDOW)tv; XVT_FNTID font_id = win_def_p->v.ctl.font_id; if (font_id == NULL) font_id = xvt_dwin_get_font(parent_win); if (font_id != NULL) { const wxFont& font = ((TFontId*)font_id)->Font(NULL, win); tv->SetFont(font); } } break; default: SORRY_BOX(); break; } if (win != NULL) { wxWindow& w = *(wxWindow*)win; const long flags = win_def_p->v.ctl.flags; if (flags & CTL_FLAG_INVISIBLE) w.Hide(); if (flags & CTL_FLAG_DISABLED) w.Disable(); } return win; } void xvt_ctl_check_radio_button(WINDOW win, WINDOW* wins, int NbrWindows) { wxASSERT(NbrWindows >= 2); for (int i = 0; i < NbrWindows; i++) { wxRadioButton* rb = (wxRadioButton*)wins[i]; wxASSERT(rb != NULL && rb->IsKindOf(CLASSINFO(wxRadioButton))); rb->SetValue(win == wins[i]); } } void xvt_ctl_set_checked(WINDOW win, BOOLEAN bCheck) { wxCheckBox* cb = (wxCheckBox*)win; wxASSERT(cb != NULL); cb->SetValue(bCheck != 0); } /////////////////////////////////////////////////////////// // Pane interface /////////////////////////////////////////////////////////// BOOLEAN xvt_win_add_pane(WINDOW win, WINDOW pane, const char* name, int dock, int flags) { BOOLEAN done = FALSE; if (win != NULL_WIN && pane != NULL_WIN && name && *name) { done = ((TwxWindow*)win)->AddPane((wxWindow*)pane, name, dock, flags); } return done; } /////////////////////////////////////////////////////////// // Notebook interface /////////////////////////////////////////////////////////// #define CAST_NOTEBOOK(win, nb) wxASSERT(win); TwxNoteBook& nb = *(TwxNoteBook*)win; wxNotebookPage* TwxNoteBook::AddTab(int idx, const wxString text, wxBitmap* bmp) { int imageId = -1; if (bmp != NULL) { wxImageList* il = GetImageList(); if (il == NULL) AssignImageList(il = new wxImageList(16,16)); imageId = il->Add(*bmp); } wxNotebookPage* nbp = new TwxWindow(this, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, 0); if (idx < 0 || idx >= (int)GetPageCount()) AddPage(nbp, text, false, imageId); else InsertPage(idx, nbp, text, false, imageId); return nbp; } TwxNoteBook::TwxNoteBook(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size) : wxNotebook(parent, id, pos, size) {} void xvt_notebk_add_page(WINDOW notebk, short tab_no, short page_no, const char* title, long page_data) { wxASSERT(page_no == 0); CAST_NOTEBOOK(notebk, nb); if (tab_no < 0 || tab_no >= (int)nb.GetPageCount()) { tab_no = nb.GetPageCount(); xvt_notebk_add_tab(notebk, tab_no, title, NULL); } TwxWindow* nbp = (TwxWindow*)nb.GetPage(tab_no); nbp->SetLabel(title); nbp->_app_data = page_data; nbp->SetBackgroundStyle(wxBG_STYLE_CUSTOM); // Lo sfondo viene disegnato nella OnPaint } void xvt_notebk_add_tab(WINDOW notebk, short tab_no, const char* title, XVT_IMAGE image) { CAST_NOTEBOOK(notebk, nb); nb.AddTab(tab_no, title, NULL); } WINDOW xvt_notebk_create_face(WINDOW notebk, short tab_no, short page_no, EVENT_MASK mask, EVENT_HANDLER face_eh, long app_data) { return xvt_notebk_create_face_def(notebk, tab_no, page_no, NULL, mask, face_eh, app_data); } WINDOW xvt_notebk_create_face_def(WINDOW notebk, short tab_no, short WXUNUSED(page_no), WIN_DEF* win_def_p, EVENT_MASK WXUNUSED(mask), EVENT_HANDLER face_eh, long app_data) { wxASSERT(tab_no >= 0 && tab_no < xvt_notebk_get_num_tabs(notebk)); CAST_NOTEBOOK(notebk, nb); TwxWindow* nbp = (TwxWindow*)nb.GetPage(tab_no); wxWindowID id = 10001+tab_no; wxString text; long style = 0; if (win_def_p != NULL) { id = win_def_p->v.ctl.ctrl_id; text = win_def_p->text; style = win_def_p->v.ctl.flags; } if (!text.IsEmpty()) nbp->SetLabel(text); if (id > 0) nbp->SetId(id); nbp->_eh = face_eh; nbp->_app_data = app_data; return (WINDOW)nbp; } WINDOW xvt_notebk_get_face(WINDOW notebk, short tab_no, short page_no) { wxASSERT(tab_no >= 0 && tab_no < xvt_notebk_get_num_tabs(notebk)); wxASSERT(page_no == 0); CAST_NOTEBOOK(notebk, nb); return (WINDOW)nb.GetPage(tab_no); } short xvt_notebk_get_num_tabs(WINDOW notebk) { CAST_NOTEBOOK(notebk, nb); return nb.GetPageCount(); } void xvt_notebk_set_front_page(WINDOW notebk, short tab_no, short page_no) { #if wxCHECK_VERSION(2,8,7) CAST_NOTEBOOK(notebk, nb); nb.ChangeSelection(tab_no); // Non generare eventi di cambio pagina! #endif } void xvt_notebk_set_tab_title(WINDOW notebk, short tab_no, const char* title) { CAST_NOTEBOOK(notebk, nb); nb.SetPageText(tab_no, title); } /////////////////////////////////////////////////////////// // TreeCtrl interface /////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(TwxTreeCtrl, wxTreeCtrl) EVT_TREE_ITEM_EXPANDING(wxID_ANY, TwxTreeCtrl::OnExpanding) EVT_TREE_ITEM_COLLAPSED(wxID_ANY, TwxTreeCtrl::OnCollapsed) EVT_TREE_SEL_CHANGED(wxID_ANY, TwxTreeCtrl::OnSelected) EVT_TREE_ITEM_ACTIVATED(wxID_ANY, TwxTreeCtrl::OnActivated) END_EVENT_TABLE(); #define CAST_TREEVIEW(win, tv) wxASSERT(win); TwxTreeCtrl& tv = *(TwxTreeCtrl*)win; struct TwxTreeItemData : public wxTreeItemData { wxString m_strData; // Assumo sempre una stringa come dati }; void TwxTreeCtrl::OnExpanding(wxTreeEvent& evt) { if (!m_nFrozen) { const wxTreeItemId id = evt.GetItem(); EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_TREE; e.v.ctl.ci.win = WINDOW(this); e.v.ctl.ci.v.treeview.node = id.m_pItem; e.v.ctl.ci.v.treeview.expanded = TRUE; if (GetChildrenCount(id) == 0) // Trucco perfido ... e.v.ctl.ci.v.treeview.collapsed = TRUE; // ... stato indeterminato = EXPANDING TwxWindow* win = (TwxWindow*)GetParent(); win->DoXvtEvent(e); if (GetChildrenCount(id) == 0) // Allora e' proprio vero ... SetItemHasChildren(id, false); } } void TwxTreeCtrl::OnCollapsed(wxTreeEvent& evt) { if (!m_nFrozen) { Suspend(); EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_TREE; e.v.ctl.ci.win = WINDOW(this); e.v.ctl.ci.v.treeview.node = evt.GetItem().m_pItem; e.v.ctl.ci.v.treeview.collapsed = TRUE; TwxWindow* win = (TwxWindow*)GetParent(); win->DoXvtEvent(e); Resume(); } } void TwxTreeCtrl::OnClick(wxTreeEvent& evt, bool bDouble) { if (!m_nFrozen) { Suspend(); EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_TREE; e.v.ctl.ci.win = WINDOW(this); e.v.ctl.ci.v.treeview.node = evt.GetItem().m_pItem; if (bDouble) e.v.ctl.ci.v.treeview.dbl_click = TRUE; else e.v.ctl.ci.v.treeview.sgl_click = TRUE; TwxWindow* win = (TwxWindow*)GetParent(); win->DoXvtEvent(e); Resume(); } } void TwxTreeCtrl::OnSelected(wxTreeEvent& evt) { OnClick(evt, false); } void TwxTreeCtrl::OnActivated(wxTreeEvent& evt) { OnClick(evt, true); } int TwxTreeCtrl::img2int(XVT_IMAGE xvt_img) { int i = -1; if (xvt_img != NULL) { #if wxCHECK_VERSION(2,8,7) i = m_img[xvt_img] - 1; // Ho memorizzato indice+1 #else i = (int)m_img.Get((long)xvt_img) - 1; #endif if (i < 0) // Immagine sconosciuta { const wxImage& img = *(wxImage*)xvt_img; wxImageList* il = GetImageList(); if (il == NULL) // Lista non ancora creata { il = new wxImageList; il->Create(img.GetWidth(), img.GetHeight(), true, 3); AssignImageList(il); // DON'T CALL SetImageList! } i = il->Add(wxBitmap(img)); #if wxCHECK_VERSION(2,8,7) m_img[xvt_img] = i+1; // Memorizzo indice+1 #else m_img.Put((long)xvt_img, (wxObject*)(i+1)); // Memorizzo indice+1 #endif } if (i < 0) SORRY_BOX(); } return i; } void TwxTreeCtrl::SetNodeImages(const wxTreeItemId& id, XVT_IMAGE item_image, XVT_IMAGE collapsed_image, XVT_IMAGE expanded_image) { const int ii = img2int(item_image); if (ii >= 0) SetItemImage(id, ii); else { const int ic = img2int(collapsed_image); if (ic >= 0) { SetItemImage(id, ic); const int ie = img2int(expanded_image); if (ie >= 0) SetItemImage(id, ie, wxTreeItemIcon_Selected); } } } wxFont TwxTreeCtrl::GetFont() const { #if wxCHECK_VERSION(2,8,7) return m_font.IsOk() ? m_font : wxTreeCtrl::GetFont(); #else return wxTreeCtrl::GetFont(); #endif } void TwxTreeCtrl::Suspend() { m_nFrozen++; } void TwxTreeCtrl::Resume() { wxASSERT(m_nFrozen > 0); if (m_nFrozen > 0) m_nFrozen--; } TwxTreeCtrl::TwxTreeCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size) : wxTreeCtrl(parent, id, pos, size, wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT), m_nFrozen(0) { AddRoot("Root"); } WINDOW xvt_treeview_create(WINDOW parent_win, RCT * rct_p, char * title, long ctl_flags, long app_data, int ctl_id, XVT_IMAGE item_image, XVT_IMAGE collapsed_image, XVT_IMAGE expanded_image, long attrs, int line_height) { WIN_DEF win_def; memset(&win_def, 0, sizeof(WIN_DEF)); win_def.wtype = WC_TREE; win_def.rct = *rct_p; win_def.text = title; win_def.v.ctl.ctrl_id = ctl_id; win_def.v.ctl.flags = ctl_flags; WINDOW win = xvt_ctl_create_def(&win_def, parent_win, app_data); return win; } XVT_TREEVIEW_NODE xvt_treeview_add_child_node(WINDOW win, XVT_TREEVIEW_NODE parent, XVT_TREEVIEW_NODE_TYPE type, XVT_IMAGE item_image, XVT_IMAGE collapsed_image, XVT_IMAGE expanded_image, const char* string, XVT_TREEVIEW_CALLBACK callback, const char* data) { XVT_TREEVIEW_NODE node = NULL; if (win != NULL_WIN) { CAST_TREEVIEW(win, tv); TwxTreeItemData* pData = new TwxTreeItemData; pData->m_strData = data; wxTreeItemId pa(parent); if (!pa.IsOk()) pa = tv.GetRootItem(); wxTreeItemId id = tv.AppendItem(pa, string, -1, -1, pData); if (id.IsOk()) { tv.SetItemHasChildren(pa, true); tv.SetItemHasChildren(id, type == XVT_TREEVIEW_NODE_NONTERMINAL); tv.SetNodeImages(id, item_image, collapsed_image, expanded_image); tv.SetItemFont(id, tv.GetFont()); node = id.m_pItem; } } return node; } XVT_TREEVIEW_NODE xvt_treeview_get_child_node(WINDOW win, XVT_TREEVIEW_NODE parent_node, int position) { XVT_TREEVIEW_NODE child_node = NULL; if (win != NULL_WIN && position >= 0) { CAST_TREEVIEW(win, tv); wxTreeItemId parent(parent_node); if (!parent.IsOk()) parent = tv.GetRootItem(); if (position < (int)tv.GetChildrenCount(parent)) { wxTreeItemIdValue cookie; wxTreeItemId id; int i = -1; for (id = tv.GetFirstChild(parent, cookie), i = -1; i < position && id.IsOk(); id = tv.GetNextChild(parent, cookie), i++); child_node = id.m_pItem; } } return child_node; } const char* xvt_treeview_get_node_data(WINDOW win, XVT_TREEVIEW_NODE node) { const char* data = NULL; if (win != NULL_WIN && node != NULL) { CAST_TREEVIEW(win, tv); const wxTreeItemId id(node); TwxTreeItemData* pData = (TwxTreeItemData*)tv.GetItemData(id); if (pData != NULL) data = (const char*)pData->m_strData; } return data; } void xvt_treeview_destroy_node(WINDOW win, XVT_TREEVIEW_NODE node) { if (win != NULL_WIN && node != NULL) { CAST_TREEVIEW(win, tv); wxTreeItemId id(node); tv.Delete(id); } } BOOLEAN xvt_treeview_expand_node(WINDOW win, XVT_TREEVIEW_NODE node, BOOLEAN recurse) { BOOLEAN ok = (win != NULL_WIN) && (node != NULL); if (ok) { CAST_TREEVIEW(win, tv); const wxTreeItemId id(node); #if wxCHECK_VERSION(2,8,7) if (recurse) tv.ExpandAllChildren(id); else #endif tv.Expand(id); } return ok; } XVT_TREEVIEW_NODE xvt_treeview_get_root_node(WINDOW win) { XVT_TREEVIEW_NODE pRoot = NULL; if (win != NULL_WIN) { CAST_TREEVIEW(win, tv); const wxTreeItemId id = tv.GetRootItem(); pRoot = id.m_pItem; } return pRoot; } XVT_TREEVIEW_NODE xvt_treeview_get_selected_node(WINDOW win) { CAST_TREEVIEW(win, tv); const wxTreeItemId id = tv.GetSelection(); return id.m_pItem; } BOOLEAN xvt_treeview_remove_child_node(WINDOW win, XVT_TREEVIEW_NODE node) { BOOLEAN ok = (win != NULL_WIN) && (node != NULL); if (ok) { CAST_TREEVIEW(win, tv); const wxTreeItemId id(node); tv.Delete(id); } return ok; } BOOLEAN xvt_treeview_remove_node_children(WINDOW win, XVT_TREEVIEW_NODE node) { BOOLEAN ok = FALSE; if (win != NULL_WIN) { CAST_TREEVIEW(win, tv); wxTreeItemId id(node); if (!id.IsOk()) id = tv.GetRootItem(); tv.DeleteChildren(id); ok = TRUE; } return ok; } void xvt_treeview_resume(WINDOW win) { CAST_TREEVIEW(win, tv); tv.Resume(); } void xvt_treeview_select_node(WINDOW win, XVT_TREEVIEW_NODE node, BOOLEAN sel) { if (win != NULL_WIN && node != NULL) { CAST_TREEVIEW(win, tv); const wxTreeItemId id(node); tv.SelectItem(id, sel != 0); if (sel) tv.EnsureVisible(id); } } void xvt_treeview_set_node_images(WINDOW win, XVT_TREEVIEW_NODE node, XVT_IMAGE item_image, XVT_IMAGE collapsed_image, XVT_IMAGE expanded_image) { if (win != NULL_WIN && node != NULL) { CAST_TREEVIEW(win, tv); const wxTreeItemId id(node); tv.SetNodeImages(id, item_image, collapsed_image, expanded_image); } } void xvt_treeview_set_node_string(WINDOW win, XVT_TREEVIEW_NODE node, const char* text) { if (win != NULL_WIN && node != NULL) { CAST_TREEVIEW(win, tv); const wxTreeItemId id(node); tv.SetItemText(id, text); } } void xvt_treeview_suspend(WINDOW win) { CAST_TREEVIEW(win, tv); tv.Suspend(); }