#include "wxinc.h" #include "xvt.h" #include "xvtwin.h" #include "statbar.h" #include #include #include #include /////////////////////////////////////////////////////////// // Utility functions /////////////////////////////////////////////////////////// static wxBitmap Image2Bitmap(XVT_IMAGE image, int maxx, int maxy, BOOLEAN trans) { if (image == NULL) return wxNullBitmap; wxImage img = *(wxImage*)image; int w = img.GetWidth(), h = img.GetHeight(); if (w > maxx || h > maxy) { const double mx = (maxx / 4) * 4, my = (maxy / 4) * 4; const double rx = mx / w, ry = my / h; const double r = rx < ry ? rx : ry; w = int(w * r); h = int(h * r); img.Rescale(w, h, wxIMAGE_QUALITY_HIGH); } if (trans && !img.HasMask()) { const int r = img.GetRed(0,0); const int g = img.GetGreen(0,0); const int b = img.GetBlue(0,0); img.SetMask(); img.SetMaskColour(r, g, b); } return wxBitmap(img); } static int RoundToIcon(int nSize) { nSize = ((nSize+3) / 8) * 8; if (nSize < 16) nSize = 16; if (nSize > 128) nSize = 128; return nSize; } const wxBitmap& _GetToolResource(int nIcon, int nDesiredSize) { static wxHashTable _tool_icons; if (nDesiredSize < 16) nDesiredSize = 16; else if (nDesiredSize > 128) nDesiredSize = 128; const long nCode = 1000*nIcon + nDesiredSize; wxBitmap* bmp = wxDynamicCast(_tool_icons.Get(nCode), wxBitmap); if (bmp == NULL) { const int nIco[] = { nIcon, 100, ICON_RSRC, 0 }; for (int i = 0; nIco[i]; i++) { wxString strName = _GetResourceName("Tool", nIco[i]).Lower(); if (!strName.IsEmpty() && ::wxFileExists(strName)) { if (strName.EndsWith(".ico")) { const wxIcon ico(strName, wxBITMAP_TYPE_ICO); bmp = new wxBitmap(ico); } else { wxImage img(strName, wxBITMAP_TYPE_ANY); img.Rescale(nDesiredSize, nDesiredSize, wxIMAGE_QUALITY_HIGH); bmp = new wxBitmap(img); } break; } } _tool_icons.Put(nCode, bmp); } return *bmp; } static wxAuiDockArt* FindArtist(wxWindow* pWindow) { wxAuiDockArt* pArtist = NULL; const wxAuiManager* pManager = wxAuiManager::GetManager(pWindow); if (pManager != NULL) pArtist = pManager->GetArtProvider(); return pArtist; } /////////////////////////////////////////////////////////// // 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 wxAuiNotebook { enum { BOOK_ICO_SIZE = 16 }; bool m_bSuspended; DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(TwxNoteBook) protected: virtual bool SetBackgroundColour(const wxColour& col); void OnPageChanged(wxAuiNotebookEvent& e); long Flags2Style(long flags) const; TwxNoteBook() {} public: int ChangeSelection(size_t tab_no); // wxNotebook had it! void SetTabImage(size_t tab_no, XVT_IMAGE img); short AddTab(wxWindow* pPage, const wxString text, XVT_IMAGE img = NULL, short idx = -1); TwxNoteBook(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style); ~TwxNoteBook(); }; class TwxTreeCtrl : public wxTreeCtrl { WX_DECLARE_VOIDPTR_HASH_MAP(int, XVT_IMAGE_Map); XVT_IMAGE_Map m_img; 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) void OnRightDown(wxMouseEvent& e); public: void SetNodeImages(const wxTreeItemId& id, XVT_IMAGE item_image, XVT_IMAGE collapsed_image, XVT_IMAGE expanded_image); void Suspend(); void Resume(); TwxTreeCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size); }; struct TwxOutlookItem { wxString m_strText; short m_nIconId; int m_nFlags; }; class TwxOutlookBar : public wxVListBox { enum { MAX_ITEMS = 32 }; TwxOutlookItem m_item[MAX_ITEMS]; int m_nHovering; DECLARE_EVENT_TABLE() protected: virtual void OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const; virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const; virtual wxCoord OnMeasureItem(size_t n) const; virtual void OnMouseMove(wxMouseEvent& e); virtual void OnMouseLeave(wxMouseEvent& e); virtual void OnSelected(wxCommandEvent& e); public: int Add(short nIconId, const wxString strText, int nFlags); TwxOutlookBar(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style); ~TwxOutlookBar(); }; class TwxPopUp : public wxVListBox { wxArrayString m_menu; int m_nHovering; wxCoord m_nRowHeight; wxColour m_clrBack, m_clrFore; DECLARE_EVENT_TABLE() void NotifySelection(); protected: virtual void OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const; virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const; virtual wxCoord OnMeasureItem(size_t n) const; virtual void OnMouseMove(wxMouseEvent& e); virtual void OnKillFocus(wxFocusEvent& e); virtual void OnSelected(wxCommandEvent& e); virtual void OnKeyDown(wxKeyEvent& e); public: int Add(const wxString str); void SetSelectForeColor(const wxColour& rgb) { m_clrFore = rgb; } void SetSelectBackColor(const wxColour& rgb) { m_clrBack= rgb; } TwxPopUp(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 = wxStaticCast((wxObject*)parent_win, wxWindow); 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 */ { long style = win_def_p->wtype == WC_HSCROLL ? wxSB_HORIZONTAL : wxSB_VERTICAL; style |= wxCLIP_SIBLINGS; 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_HSLIDER: /* horizontal slider control */ case WC_VSLIDER: /* vertical slider control */ { const long style = win_def_p->wtype == WC_HSLIDER ? wxSL_HORIZONTAL : wxSL_VERTICAL; wxSlider* sc = new wxSlider(pParent, id, 0, 0, app_data, rct.GetPosition(), rct.GetSize(), style); win = (WINDOW)sc; } 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 pb = new wxBitmapButton(pParent, id, wxNullBitmap, rct.GetPosition(), rct.GetSize()); win = (WINDOW)pb; } break; case WC_CHECKBOX: /* check box */ { long style = wxCHK_2STATE | wxCLIP_SIBLINGS; 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 */ { const long style = wxRB_SINGLE | wxCLIP_SIBLINGS; wxRadioButton* rb = new wxRadioButton(pParent, id, win_def_p->text, rct.GetPosition(), rct.GetSize(), style); win = (WINDOW)rb; } break; case WC_NOTEBK: { TwxNoteBook* nb = new TwxNoteBook(pParent, id, rct.GetPosition(), rct.GetSize(), win_def_p->v.ctl.flags); win = (WINDOW)nb; } break; case WC_TREE: { TwxTreeCtrl* tv = new TwxTreeCtrl(pParent, id, rct.GetPosition(), rct.GetSize()); win = (WINDOW)tv; } break; case WC_LBOX: { wxListBox* tlb = new wxListBox(pParent, id, rct.GetPosition(), rct.GetSize()); win = (WINDOW)tlb; } break; case WC_POPUP: { TwxPopUp* tpu = new TwxPopUp(pParent, id, rct.GetPosition(), rct.GetSize()); win = (WINDOW)tpu; } break; case WC_OUTLOOKBAR: { long style = 0; TwxOutlookBar* tob = new TwxOutlookBar(pParent, id, rct.GetPosition(), rct.GetSize(), style); win = (WINDOW)tob; } break; default: SORRY_BOX(); break; } if (win != NULL_WIN) { wxWindow& w = *wxStaticCast((wxObject*)win, wxWindow); const long flags = win_def_p->v.ctl.flags; if (flags & CTL_FLAG_INVISIBLE) w.Hide(); if (flags & CTL_FLAG_DISABLED) w.Disable(); XVT_FNTID font_id = win_def_p->v.ctl.font_id; const bool bDestroyFont = font_id == NULL; if (bDestroyFont) font_id = xvt_dwin_get_font(parent_win); if (font_id != NULL) { const wxFont& font = wxStaticCast(font_id, TFontId)->Font(NULL, win); w.SetFont(font); if (bDestroyFont) xvt_font_destroy(font_id); } xvt_ctl_set_colors(win, win_def_p->ctlcolors, XVT_COLOR_ACTION_SET); } 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 = wxDynamicCast((wxObject*)wins[i], wxRadioButton); if (rb != NULL) rb->SetValue(win == wins[i]); } } void xvt_ctl_set_checked(WINDOW win, BOOLEAN bCheck) { wxCheckBox* cb = wxDynamicCast((wxObject*)win, wxCheckBox); if (cb != NULL) cb->SetValue(bCheck != 0); } void xvt_ctl_set_colors(WINDOW win, const XVT_COLOR_COMPONENT* colors, XVT_COLOR_ACTION action) { // Non posso usare wxControl in quanto certi controlli derivano da wxWindow wxWindow* w = wxDynamicCast((wxObject*)win, wxWindow); if (w != NULL && colors != NULL) { if (action == XVT_COLOR_ACTION_SET) { for (int i = 0; colors[i].type; i++) { CAST_COLOR(colors[i].color, rgb); switch(colors[i].type) { case XVT_COLOR_BACKGROUND: w->SetOwnBackgroundColour(rgb); break; case XVT_COLOR_FOREGROUND: w->SetOwnForegroundColour(rgb); break; case XVT_COLOR_HIGHLIGHT: { TwxPopUp* tpu = wxDynamicCast(w, TwxPopUp); if (tpu != NULL) tpu->SetSelectForeColor(rgb); } break; case XVT_COLOR_SELECT: { TwxPopUp* tpu = wxDynamicCast(w, TwxPopUp); if (tpu != NULL) tpu->SetSelectBackColor(rgb); } break; case XVT_COLOR_BLEND: if (!w->IsKindOf(CLASSINFO(wxButton))) w->SetOwnBackgroundColour(rgb); break; default: break; } } } else { // ??? } } } /////////////////////////////////////////////////////////// // Buttons /////////////////////////////////////////////////////////// void xvt_btn_set_images(WINDOW win, XVT_IMAGE up, XVT_IMAGE down) { if (win != NULL_WIN && up != NULL) { wxBitmapButton* pb = wxDynamicCast((wxObject*)win, wxBitmapButton); if (pb != NULL) { int mx, my; pb->GetSize(&mx, &my); wxBitmap bmpUp(Image2Bitmap(up, mx, my, TRUE)); if (bmpUp.Ok()) { pb->SetBitmapLabel(bmpUp); const wxImage imgGay = ((wxImage*)up)->ConvertToGreyscale(); wxBitmap bmpGay(imgGay); pb->SetBitmapDisabled(bmpGay); } if (down != NULL) { wxBitmap bmpDown(Image2Bitmap(down, mx, my, TRUE)); if (bmpDown.Ok()) pb->SetBitmapSelected(bmpDown); } else { if (bmpUp.Ok()) pb->SetBitmapSelected(bmpUp); } } } } /////////////////////////////////////////////////////////// // Pane interface /////////////////////////////////////////////////////////// static wxAuiManager* FindPaneManager(WINDOW win) { wxAuiManager* pManager = NULL; if (win != NULL_WIN) { wxWindow* pwin = wxStaticCast((wxObject*)win, wxWindow); pManager = wxAuiManager::GetManager(pwin); } return pManager; } static wxAuiPaneInfo* LockPane(WINDOW win) { wxAuiManager* pManager = FindPaneManager(win); if (pManager != NULL) { wxAuiPaneInfo& pane = pManager->GetPane((wxWindow*)win); if (pane.IsOk()) return &pane; } return NULL; } static void UnlockPane(WINDOW win) { wxAuiManager* pManager = FindPaneManager(win); if (pManager != NULL) pManager->Update(); } BOOLEAN xvt_pane_add(WINDOW win, WINDOW pane, const char* name, int dock, int flags) { BOOLEAN done = FALSE; if (win != NULL_WIN && pane != NULL_WIN && name && *name) { TwxWindow* owner = wxStaticCast((wxObject*)win, TwxWindow); wxWindow* child = wxStaticCast((wxObject*)pane, wxWindow); done = owner->AddPane(child, name, dock, flags); } return done; } BOOLEAN xvt_pane_set_title(WINDOW win, const char* title) { wxAuiPaneInfo* pane = LockPane(win); if (pane != NULL) { pane->Caption(title); UnlockPane(win); } return pane != NULL; } XVTDLL BOOLEAN xvt_pane_change_flags(WINDOW win, int set, int rst) { wxAuiPaneInfo* pane = LockPane(win); if (pane != NULL && (set || rst)) { if (set) pane->SetFlag(set, true); if (rst) pane->SetFlag(rst, false); UnlockPane(win); } return pane != NULL; } XVTDLL BOOLEAN xvt_pane_detach(WINDOW win) { BOOLEAN ok = FALSE; wxAuiManager* pManager = FindPaneManager(win); if (pManager != NULL) { ok = pManager->DetachPane((wxWindow*)win); pManager->Update(); } return ok; } XVTDLL BOOLEAN xvt_pane_manager_load_perspective(WINDOW win, const char* perspective) { BOOLEAN ok = FALSE; if (perspective && *perspective) { wxAuiManager* pManager = FindPaneManager(win); if (pManager != NULL) { const wxString str = perspective; ok = pManager->LoadPerspective(str, true); } } return ok; } XVTDLL int xvt_pane_manager_save_perspective(WINDOW win, char* perspective, int max_size) { int nSize = 0; wxAuiManager* pManager = FindPaneManager(win); if (pManager != NULL) { const wxString str = pManager->SavePerspective(); nSize = str.Len()+1; if (perspective != NULL && max_size > 0) wxStrncpy(perspective, str, max_size); } return nSize; } XVTDLL BOOLEAN xvt_pane_set_size_range(WINDOW win, int min_size, int best_size, int max_size) { BOOLEAN ok = FALSE; wxAuiPaneInfo* pane = LockPane(win); if (pane != NULL) { if (min_size > 0 || max_size > 0) { if (best_size <= 0) { if (min_size > 0) best_size = max_size > 0 ? (min_size+max_size) / 2 : min_size; else best_size = max_size; } wxSize szMin(-1, -1), szBst(-1, -1), szMax(-1, -1); if (pane->IsTopDockable() || pane->IsBottomDockable()) { szMin.y = min_size; szBst.y = best_size; szMax.y = max_size; } else { szMin.x = min_size; szBst.x = best_size; szMax.x = max_size; } pane->MinSize(szMin); pane->BestSize(szBst); pane->MaxSize(szMax); } pane->Resizable(min_size != max_size); pane->DockFixed(min_size == max_size); UnlockPane(win); } return ok; } /////////////////////////////////////////////////////////// // Notebook interface /////////////////////////////////////////////////////////// class TwxAuiDefaultTabArt : public wxAuiDefaultTabArt { public: void SetBackgroundColour(const wxColor& colour) { m_base_colour = colour; } virtual wxAuiTabArt* Clone(); }; wxAuiTabArt* TwxAuiDefaultTabArt::Clone() { TwxAuiDefaultTabArt* art = new TwxAuiDefaultTabArt(); // Copy'n'paste from aui/auibook.cpp art->SetNormalFont(m_normal_font); art->SetSelectedFont(m_selected_font); art->SetMeasuringFont(m_measuring_font); // My own addition art->m_base_colour = m_base_colour; return art; } IMPLEMENT_DYNAMIC_CLASS(TwxNoteBook, wxAuiNotebook) #define CAST_NOTEBOOK(win, nb) TwxNoteBook& nb = *wxStaticCast((wxObject*)win, TwxNoteBook); inline bool VALID_NOTEBOOK(WINDOW notebk, short page_no) { return page_no >= 0 && wxDynamicCast((wxObject*)notebk, TwxNoteBook)!=NULL; } BEGIN_EVENT_TABLE(TwxNoteBook, wxAuiNotebook) EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY, OnPageChanged) END_EVENT_TABLE(); bool TwxNoteBook::SetBackgroundColour(const wxColour& col) { const bool ok = wxAuiNotebook::SetBackgroundColour(col); if (ok) // Se cambio lo sfondo del tab control devo notificarlo all'art provider { TwxAuiDefaultTabArt* pArtist = (TwxAuiDefaultTabArt*)GetArtProvider(); if (pArtist != NULL) pArtist->SetBackgroundColour(col); } return ok; } void TwxNoteBook::OnPageChanged(wxAuiNotebookEvent& evt) { if (!m_bSuspended) { m_bSuspended = true; EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_NOTEBK; e.v.ctl.ci.win = WINDOW(this); e.v.ctl.ci.v.notebk.face = (WINDOW)GetPage(evt.GetSelection()); e.v.ctl.ci.v.notebk.tab_no = evt.GetSelection(); e.v.ctl.ci.v.notebk.page_no = evt.GetOldSelection(); TwxWindow* win = wxStaticCast(GetParent(), TwxWindow); win->DoXvtEvent(e); m_bSuspended = false; } } short TwxNoteBook::AddTab(wxWindow* pPage, const wxString text, XVT_IMAGE xvt_img, short idx) { wxBitmap bmp; if (xvt_img != NULL) bmp = Image2Bitmap(xvt_img, BOOK_ICO_SIZE, BOOK_ICO_SIZE, TRUE); if (idx < 0 || idx >= (int)GetPageCount()) { AddPage(pPage, text, false, bmp); idx = GetPageCount()-1; } else InsertPage(idx, pPage, text, false, bmp); return idx; } void TwxNoteBook::SetTabImage(size_t idx, XVT_IMAGE img) { if (img != NULL) { wxImage ico(*wxStaticCast(img, wxImage)); ico.Rescale(BOOK_ICO_SIZE, BOOK_ICO_SIZE, wxIMAGE_QUALITY_HIGH); const wxBitmap bmp(ico); SetPageBitmap(idx, bmp); } else SetPageBitmap(idx, wxNullBitmap); } int TwxNoteBook::ChangeSelection(size_t tab_no) { const size_t nSel = GetSelection(); if (!m_bSuspended && tab_no != nSel) { m_bSuspended = true; SetSelection(tab_no); m_bSuspended = false; } return nSel; } long TwxNoteBook::Flags2Style(long flags) const { long style = wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS; bool bottom = false; #if wxCHECK_VERSION(2,8,9) if (flags & (CTL_FLAG_TAB_TOP|CTL_FLAG_TAB_BOTTOM|CTL_FLAG_TAB_LEFT|CTL_FLAG_TAB_RIGHT)) { bottom = (flags & CTL_FLAG_TAB_BOTTOM) != 0; } else #endif { bottom = (flags & CTL_FLAG_CENTER_JUST) != 0; } if (bottom) style |= wxAUI_NB_BOTTOM; else style |= wxAUI_NB_TOP; return style; } TwxNoteBook::TwxNoteBook(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long flags) : wxAuiNotebook(parent, id, pos, size, Flags2Style(flags)), m_bSuspended(false) { SetArtProvider(new TwxAuiDefaultTabArt); _nice_windows.Put((WINDOW)this, this); // Serve per poter fare la xvt_vobj_destroy } TwxNoteBook::~TwxNoteBook() { m_bSuspended = true; _nice_windows.Delete((WINDOW)this); } short xvt_notebk_add_page(WINDOW notebk, WINDOW page, const char* title, XVT_IMAGE image, short tab_no) { short idx = -1; if (notebk != NULL_WIN) { CAST_NOTEBOOK(notebk, nb); wxString strTitle = title; if (strTitle.IsEmpty() && page != NULL_WIN) { wxWindow* pg = wxStaticCast((wxObject*)page, wxWindow); strTitle = pg->GetLabel(); } idx = nb.AddTab((wxWindow*)page, strTitle, image, tab_no); } return idx; } WINDOW xvt_notebk_get_page(WINDOW notebk, short tab_no) { WINDOW page = NULL_WIN; if (VALID_NOTEBOOK(notebk, tab_no)) { CAST_NOTEBOOK(notebk, nb); page = (WINDOW)nb.GetPage(tab_no); } return page; } short xvt_notebk_get_num_tabs(WINDOW notebk) { short pg = 0; if (notebk != NULL_WIN) { CAST_NOTEBOOK(notebk, nb); pg = nb.GetPageCount(); } return pg; } void xvt_notebk_rem_page(WINDOW notebk, short page_no) { WINDOW win = xvt_notebk_get_page(notebk, page_no); if (win != NULL_WIN) { xvt_notebk_rem_tab(notebk, page_no); xvt_vobj_destroy(win); } } void xvt_notebk_rem_tab(WINDOW notebk, short tab_no) { if (VALID_NOTEBOOK(notebk, tab_no)) { CAST_NOTEBOOK(notebk, nb); nb.RemovePage(tab_no); } } void xvt_notebk_set_front_page(WINDOW notebk, short tab_no) { if (VALID_NOTEBOOK(notebk, tab_no)) { CAST_NOTEBOOK(notebk, nb); wxWindow* w = nb.GetPage(tab_no); if (w != NULL) { nb.ChangeSelection(tab_no); // Non genera evento di cambio pagina! if (!w->IsShown()) // A volte succede che la prima pagina sia nascosta! w->Show(true); } } } char* xvt_notebk_get_tab_title(WINDOW notebk, short tab_no, char* title, int sz_title) { if (VALID_NOTEBOOK(notebk, tab_no)) { CAST_NOTEBOOK(notebk, nb); wxStrncpy(title, nb.GetPageText(tab_no), sz_title); title[sz_title-1] = '\0'; } else *title = '\0'; return title; } void xvt_notebk_set_page_title(WINDOW notebk, short tab_no, const char* title) { WINDOW win = xvt_notebk_get_page(notebk, tab_no); if (win != NULL_WIN) xvt_vobj_set_title(win, title); } void xvt_notebk_set_tab_image(WINDOW notebk, short tab_no, XVT_IMAGE img) { if (notebk != NULL_WIN && tab_no >= 0) { CAST_NOTEBOOK(notebk, nb); nb.SetTabImage(tab_no, img); // Se img=NULL toglie l'immagine } } void xvt_notebk_set_tab_icon(WINDOW notebk, short tab_no, int rid) { const wxString strName = _GetResourceName("Icon", rid); XVT_IMAGE img = xvt_image_read(strName); xvt_notebk_set_tab_image(notebk, tab_no, img); xvt_image_destroy(img); } void xvt_notebk_set_tab_title(WINDOW notebk, short tab_no, const char* title) { if (VALID_NOTEBOOK(notebk, tab_no)) { CAST_NOTEBOOK(notebk, nb); const short pc = nb.GetPageCount(); if (tab_no >= pc) nb.AddTab(nb.GetPage(pc-1), title, NULL, pc); else 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) EVT_RIGHT_DOWN(TwxTreeCtrl::OnRightDown) END_EVENT_TABLE(); #define CAST_TREEVIEW(win, tv) TwxTreeCtrl& tv = *wxStaticCast((wxObject*)win, TwxTreeCtrl); 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 = wxStaticCast(GetParent(), TwxWindow); 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 = wxStaticCast(GetParent(), TwxWindow); 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 = wxStaticCast(GetParent(), TwxWindow); win->DoXvtEvent(e); Resume(); } } void TwxTreeCtrl::OnSelected(wxTreeEvent& evt) { OnClick(evt, false); } void TwxTreeCtrl::OnActivated(wxTreeEvent& evt) { OnClick(evt, true); } void TwxTreeCtrl::OnRightDown(wxMouseEvent& evt) { TwxWindow* pParent = wxDynamicCast(GetParent(), TwxWindow); if (pParent != NULL) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_MOUSE_DOWN; e.v.mouse.button = 1; 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(); pParent->DoXvtEvent(e); } } int TwxTreeCtrl::img2int(XVT_IMAGE xvt_img) { int i = -1; if (xvt_img != NULL) { i = m_img[xvt_img] - 1; // Ho memorizzato indice+1 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! } else { int old_w, old_h; il->GetSize(0, old_w, old_h); const int new_w = img.GetWidth(), new_h = img.GetHeight(); if (new_w > old_w) // L'immagine nuova e' troppo grande? { const int old_ratio = old_w * 100 / old_h; const int new_ratio = new_w * 100 / new_h; const int old_count = il->GetImageCount(); wxImageList* nil = new wxImageList; nil->Create(new_w, new_h, true, 3*old_count/2); for (int k = 0; k < old_count; k++) { wxImage old = il->GetBitmap(k).ConvertToImage(); if (old_ratio == new_ratio) old.Rescale(new_w, new_h, wxIMAGE_QUALITY_HIGH); else old.Resize(wxSize(new_w, new_h), wxPoint((new_w-old_w)/2, (new_h-old_h)/2)); nil->Add(old); } AssignImageList(il = nil); } } if (!img.HasMask()) { wxImage& trans = (wxImage&)img; const int r = img.GetRed(0,0); const int g = img.GetGreen(0,0); const int b = img.GetBlue(0,0); trans.SetMask(); trans.SetMaskColour(r, g, b); } const wxBitmap bmp(img); i = il->Add(bmp); m_img[xvt_img] = i+1; // Memorizzo indice+1 } 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); } } } 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 WXUNUSED(item_image), XVT_IMAGE WXUNUSED(collapsed_image), XVT_IMAGE WXUNUSED(expanded_image), long WXUNUSED(attrs), int WXUNUSED(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 WXUNUSED(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 (parent.IsOk() && 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); tv.Suspend(); const wxTreeItemId id(node); if (recurse) tv.ExpandAllChildren(id); else tv.Expand(id); tv.Resume(); } 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); if (id == tv.GetRootItem()) tv.DeleteAllItems(); else { tv.Suspend(); tv.Delete(id); tv.Resume(); } } 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); tv.Suspend(); wxTreeItemId id(node); if (!id.IsOk()) id = tv.GetRootItem(); tv.DeleteChildren(id); tv.Resume(); 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); if (sel) { tv.Suspend(); tv.SelectItem(id, true); tv.EnsureVisible(id); tv.Resume(); } else tv.SelectItem(id, false); } } 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(); } static XVT_TREEVIEW_NODE FindTreeNodeString(wxTreeCtrl& tv, const wxTreeItemId& parent, const char*text) { if (parent.IsOk()) { TwxTreeItemData* pData = (TwxTreeItemData*)tv.GetItemData(parent); if (pData != NULL && pData->m_strData == text) return parent.m_pItem; wxTreeItemIdValue cookie; for (wxTreeItemId id = tv.GetFirstChild(parent, cookie); id.IsOk(); id = tv.GetNextChild(parent, cookie)) { XVT_TREEVIEW_NODE node = FindTreeNodeString(tv, id, text); if (node != NULL) return node; } } return NULL; } XVT_TREEVIEW_NODE xvt_treeview_find_node_string(WINDOW win, const char* text) { XVT_TREEVIEW_NODE node = NULL; if (win != NULL_WIN && text && *text) { CAST_TREEVIEW(win, tv); node = FindTreeNodeString(tv, tv.GetSelection(), text); if (node == NULL) node = FindTreeNodeString(tv, tv.GetRootItem(), text); } return node; } /////////////////////////////////////////////////////////// // TwxOutlookBar /////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(TwxOutlookBar, wxVListBox) EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_LISTBOX_SELECTED, TwxOutlookBar::OnSelected) EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, TwxOutlookBar::OnSelected) EVT_MOTION(TwxOutlookBar::OnMouseMove) EVT_LEAVE_WINDOW(TwxOutlookBar::OnMouseLeave) END_EVENT_TABLE() static const wxColour ModulateColour(const wxColour& col, int percent) { int k = 0; if (percent > 0) k = 255; else percent = -percent; const int inverse = 100-percent; int r = ((k * percent) + (col.Red() * inverse)) / 100; int g = ((k * percent) + (col.Green() * inverse)) / 100; int b = ((k * percent) + (col.Blue() * inverse)) / 100; return wxColour(r, g, b); } /* static const wxColour MeanColour(const wxColour& c1, const wxColour& c2, int percent = 50) { const double p = percent / 100.0; const double i = 1.0-p; return wxColour(c1.Red()*i+c2.Red()*p, c1.Green()*i+c2.Green()*p, c1.Blue()*i+c2.Blue()*p); } */ void TwxOutlookBar::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t u) const { const int n = u; // Anti warning wxColour color1, color2; if (n == m_nHovering) { if (n == GetSelection()) { color1 = wxColour(232,127,8); color2 = wxColour(247,218,124); } else { color1 = wxColour(255,255,220); color2 = wxColour(247,192,91); } } else { if (n == GetSelection()) { color1 = wxColour(251,230,148); // Colori predefiniti di Outlook color2 = wxColour(238,149, 21); } else { if (InheritsBackgroundColour()) { color1 = ModulateColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INACTIVECAPTION), +20); color2 = ModulateColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION), -20); } else { const wxColour bkg = GetBackgroundColour(); color1 = ModulateColour(bkg, +20); color2 = ModulateColour(bkg, -20); } } } dc.GradientFillLinear(rect, color1, color2, wxDOWN); } void TwxOutlookBar::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const { const int nSide = rect.height; const TwxOutlookItem& oi = m_item[n]; int nTextOffset = 4; if (oi.m_nIconId > 0) { const wxIcon& ico = _GetIconResource(oi.m_nIconId); const wxSize szIco(ico.GetWidth(), ico.GetHeight()); dc.DrawIcon(ico, rect.x+nTextOffset, rect.y+(nSide-szIco.y)/2); nTextOffset += nTextOffset+szIco.x; } dc.SetFont(GetFont()); // Imposta il font predefinito per questo controllo wxColour color = GetForegroundColour(); if (InheritsBackgroundColour()) color = wxSystemSettings::GetColour(wxSYS_COLOUR_CAPTIONTEXT); dc.SetTextForeground(color); const wxSize szText = dc.GetTextExtent(oi.m_strText); dc.DrawText(oi.m_strText, rect.x+nTextOffset, rect.y+(nSide-szText.y)/2); } wxCoord TwxOutlookBar::OnMeasureItem(size_t WXUNUSED(n)) const { const int nItems = GetItemCount(); wxCoord nHeight = 32 + 4; // Icon size + gap if (nItems > 1) { const wxSize sz = GetSize(); nHeight = max(sz.y / nItems, nHeight); } return nHeight; } void TwxOutlookBar::OnMouseMove(wxMouseEvent& evt) { const int nWasHovering = m_nHovering; m_nHovering = HitTest(evt.GetPosition()); if (m_nHovering != nWasHovering) { if (nWasHovering != wxNOT_FOUND) RefreshLine(nWasHovering); if (m_nHovering != wxNOT_FOUND) RefreshLine(m_nHovering); } } void TwxOutlookBar::OnMouseLeave(wxMouseEvent& WXUNUSED(e)) { if (m_nHovering != wxNOT_FOUND) { const int nWasHovering = m_nHovering; m_nHovering = wxNOT_FOUND; RefreshLine(nWasHovering); } } void TwxOutlookBar::OnSelected(wxCommandEvent& evt) { TwxWindow* win = wxDynamicCast(GetParent(), TwxWindow); if (win != NULL) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = evt.GetId(); e.v.ctl.ci.type = WC_OUTLOOKBAR; e.v.ctl.ci.win = WINDOW(this); e.v.ctl.ci.v.lbox.dbl_click = evt.GetEventType() == wxEVT_COMMAND_LISTBOX_DOUBLECLICKED; win->DoXvtEvent(e); } } int TwxOutlookBar::Add(short nIconId, const wxString strText, int nFlags) { int i = GetItemCount(); const bool ok = i < MAX_ITEMS-1; if (ok) { m_item[i].m_nIconId = nIconId; m_item[i].m_strText = strText; m_item[i].m_nFlags = nFlags; SetItemCount(i+1); } else i = -1; return i; } TwxOutlookBar::TwxOutlookBar(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : wxVListBox(parent, id, pos, size, style), m_nHovering(wxNOT_FOUND) { SetItemCount(0); } TwxOutlookBar::~TwxOutlookBar() { } BOOLEAN xvt_list_add(WINDOW win, int index, const char* text) { wxListBox* lb = wxDynamicCast((wxObject*)win, wxListBox); BOOLEAN ok = lb != NULL; if (ok) { const wxString str = text; if (index < 0 || index >= (int)lb->GetCount()) lb->AppendString(str); else lb->Insert(str, index); } return ok; } int xvt_list_add_item(WINDOW win, short icon, const char* text, int flags) { int n = -1; if (win != NULL_WIN) { TwxOutlookBar* olb = wxDynamicCast((wxObject*)win, TwxOutlookBar); if (olb != NULL) n = olb->Add(icon, text, flags); } return n; } BOOLEAN xvt_list_clear(WINDOW win) { BOOLEAN ok = win != NULL_WIN; if (ok) { wxVListBox* olb = wxDynamicCast((wxObject*)win, wxVListBox); if (olb != NULL) olb->Clear(); else { wxListBox* lb = wxDynamicCast((wxObject*)win, wxListBox); if (lb != NULL) lb->Clear(); } } return ok; } int xvt_list_get_sel_index(WINDOW win) { int sel = -1; if (win != NULL_WIN) { wxVListBox* olb = wxDynamicCast((wxObject*)win, wxVListBox); if (olb != NULL) sel = olb->GetSelection(); else { wxListBox* lb = wxDynamicCast((wxObject*)win, wxListBox); if (lb != NULL) sel = lb->GetSelection(); } } return sel; } BOOLEAN xvt_list_set_sel(WINDOW win, int index, BOOLEAN select) { BOOLEAN ok = win != NULL_WIN; if (ok) { wxVListBox* olb = wxDynamicCast((wxObject*)win, wxVListBox); if (olb != NULL) { if (select) olb->SetSelection(index); } else { wxListBox* lb = wxDynamicCast((wxObject*)win, wxListBox); if (lb != NULL) lb->SetSelection(index, select != 0); } } return ok; } int xvt_list_count(WINDOW win) { int n = 0; if (win != NULL_WIN) { wxVListBox* olb = wxDynamicCast((wxObject*)win, wxVListBox); if (olb != NULL) n = olb->GetItemCount(); else { wxListBox* lb = wxDynamicCast((wxObject*)win, wxListBox); if (lb != NULL) n = lb->GetCount(); } } return n; } /////////////////////////////////////////////////////////// // TwxPopUp /////////////////////////////////////////////////////////// BEGIN_EVENT_TABLE(TwxPopUp, wxVListBox) EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_LISTBOX_SELECTED, TwxPopUp::OnSelected) EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, TwxPopUp::OnSelected) EVT_MOTION(TwxPopUp::OnMouseMove) EVT_KILL_FOCUS(TwxPopUp::OnKillFocus) EVT_KEY_DOWN(TwxPopUp::OnKeyDown) END_EVENT_TABLE() void TwxPopUp::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t u) const { const int n = u; // Anti warning if (n == m_nHovering || (m_nHovering == wxNOT_FOUND && IsCurrent(u))) { wxBrush brush(m_clrBack); dc.SetBrush(brush); dc.SetPen(*wxTRANSPARENT_PEN); dc.DrawRectangle(rect); } } void TwxPopUp::OnDrawItem(wxDC& dc, const wxRect& rect, size_t u) const { const int n = u; // Anti warning wxColour color; if (n == m_nHovering || (m_nHovering == wxNOT_FOUND && IsCurrent(u))) color = m_clrFore; else color = GetForegroundColour(); dc.SetTextForeground(color); dc.SetFont(GetFont()); dc.DrawText(m_menu[n], rect.x, rect.y); } wxCoord TwxPopUp::OnMeasureItem(size_t WXUNUSED(n)) const { return m_nRowHeight; } void TwxPopUp::OnMouseMove(wxMouseEvent& evt) { int nHover = wxNOT_FOUND; const wxRect rect = GetClientRect(); if (rect.Contains(evt.GetPosition())) nHover = HitTest(evt.GetPosition()); if (nHover != m_nHovering) { const int nWasHovering = m_nHovering; m_nHovering = nHover; if (nWasHovering != wxNOT_FOUND) RefreshLine(nWasHovering); if (m_nHovering != wxNOT_FOUND) RefreshLine(m_nHovering); } } void TwxPopUp::OnKillFocus(wxFocusEvent& WXUNUSED(e)) { Hide(); } void TwxPopUp::NotifySelection() { TwxWindow* win = wxDynamicCast(GetParent(), TwxWindow); if (win != NULL) { EVENT e; memset(&e, 0, sizeof(EVENT)); e.type = E_CONTROL; e.v.ctl.id = GetId(); e.v.ctl.ci.type = WC_LISTEDIT; e.v.ctl.ci.win = WINDOW(this); e.v.ctl.ci.v.listedit.active = GetSelection(); win->DoXvtEvent(e); } Hide(); } void TwxPopUp::OnSelected(wxCommandEvent& WXUNUSED(evt)) { if (m_nHovering >= 0) NotifySelection(); } int TwxPopUp::Add(const wxString str) { m_menu.Add(str); const int i = m_menu.GetCount(); SetItemCount(i); return i; } void TwxPopUp::OnKeyDown(wxKeyEvent& evt) { m_nHovering = wxNOT_FOUND; // Evita chiusura involontaria della lista int key = evt.GetKeyCode(); switch (key) { case WXK_RETURN: NotifySelection(); break; default: if (key > ' ' && key <= 'z') { key = toupper(key); const int curr = max(GetSelection(), 0); const int tot = m_menu.GetCount(); int i = curr; for (i = (i+1)%tot; i != curr; i = (i+1)%tot) { if (toupper(m_menu[i][0]) == key) break; } SetSelection(i); } else evt.Skip(); break; } } TwxPopUp::TwxPopUp(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size) : wxVListBox(parent, id, pos, size, wxBORDER|wxCLIP_SIBLINGS), m_nHovering(wxNOT_FOUND) { m_clrFore = wxSystemSettings::GetColour(wxSYS_COLOUR_HOTLIGHT); m_clrBack = GetSelectionBackground(); const wxFont font = parent->GetFont(); m_nRowHeight = abs(font.GetPixelSize().y) + 8; } static int RoundPopupHeight(int list_h, int row_h) { const int rem = list_h % row_h; if (rem > 0) list_h -= rem; return list_h; } MENU_TAG xvt_list_popup(WINDOW parent_win, const RCT* ownrct, const MENU_ITEM* menu, const XVT_COLOR_COMPONENT* colors, MENU_TAG first) { int sel = -1; int items = 0; if (parent_win != NULL_WIN && ownrct != NULL && menu != NULL) { wxWindow* parent = wxStaticCast((wxObject*)parent_win, wxWindow); int width = ownrct->right - ownrct->left; for (items = 0; menu[items].tag != 0; items++) if (menu[items].tag > 0 && menu[items].text) { const wxString str = menu[items].text; int w = 0, h = 0; parent->GetTextExtent(str, &w, &h); w += 24; if (w > width) width = w; } const wxFont font = parent->GetFont(); const int nRowHeight = abs(font.GetPixelSize().y)+8; const wxRect rctClient = parent->GetClientRect(); const int nBottom = rctClient.GetBottom(); wxPoint pos(ownrct->right-width, ownrct->bottom); wxSize size(width, items*nRowHeight); if (pos.y + size.y > nBottom) // La lista deborda di sotto? { if (ownrct->top > nBottom-ownrct->bottom) // Ho piu' spazio sopra che sotto? { pos.y = ownrct->top - size.y; // Sposto la lista sopra al campo di testo if (pos.y < 0) { size.y = RoundPopupHeight(size.y + pos.y, nRowHeight); pos.y = ownrct->top - size.y; } } else { // Accorcio la lista in basso size.y = RoundPopupHeight(nBottom-pos.y, nRowHeight); } } if (pos.x < 0) pos.x = 0; WIN_DEF wd; memset(&wd, 0, sizeof(wd)); wd.ctlcolors = (XVT_COLOR_COMPONENT*)colors; xvt_rect_set(&wd.rct, pos.x, pos.y, pos.x+size.x, pos.y+size.y); wd.v.ctl.ctrl_id = wxID_ANY; wd.v.ctl.flags = CTL_FLAG_INVISIBLE; wd.wtype = WC_POPUP; WINDOW win = xvt_ctl_create_def(&wd, parent_win, 0); TwxPopUp* lb = wxDynamicCast((wxObject*)win, TwxPopUp); if (lb != NULL) { for (int i = 0; menu[i].tag != 0; i++) { const MENU_ITEM& mi = menu[i]; if (mi.tag > 0) { lb->Add(mi.text); if (mi.tag == first) sel = i; } } if (sel >= 0) lb->SetSelection(sel); lb->Show(); lb->SetFocus(); while (lb->IsShown()) { wxApp* a = wxTheApp; // Memorizzo il risultato di wxGetInstance while (a->Pending()) a->Dispatch(); lb->Raise(); wxMilliSleep(50); } sel = lb->GetSelection(); delete lb; } } return sel >= 0 && sel < items ? menu[sel].tag : 0; } /////////////////////////////////////////////////////////// // ToolBar /////////////////////////////////////////////////////////// #if wxCHECK_VERSION(8,8,3) #include #define TwxToolBarBase wxAuiToolBar #else #define TwxToolBarBase wxToolBar #endif class TwxToolBar : public TwxToolBarBase { DECLARE_DYNAMIC_CLASS(TwxToolBar) protected: DECLARE_EVENT_TABLE() void OnTool(wxCommandEvent& evt); virtual bool SetBackgroundColour(const wxColour& colour); TwxToolBar() : TwxToolBarBase(NULL, wxID_ANY) { wxASSERT(false); } public: void ShowTool(int id, bool on); TwxToolBar(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style); }; IMPLEMENT_DYNAMIC_CLASS(TwxToolBar, TwxToolBarBase) BEGIN_EVENT_TABLE(TwxToolBar, TwxToolBarBase) EVT_TOOL(wxID_ANY, TwxToolBar::OnTool) END_EVENT_TABLE(); void TwxToolBar::OnTool(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_ICON; // WC_PUSHBUTTON entra in conflitto coi bottoni e.v.ctl.ci.win = WINDOW(this); TwxWindow* win = wxStaticCast(GetParent(), TwxWindow); win->DoXvtEvent(e); } bool TwxToolBar::SetBackgroundColour(const wxColour& colour) { const bool ok = TwxToolBarBase::SetBackgroundColour(colour); if (ok) // Se cambio lo sfondo della toolbar devo aggiornare anche quello del gripper { wxAuiDockArt* pArtist = FindArtist(this); if (pArtist != NULL) pArtist->SetColor(wxAUI_DOCKART_GRIPPER_COLOUR, colour); } return ok; } TwxToolBar::TwxToolBar(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : TwxToolBarBase(parent, id, pos, size, style) { } static TwxToolBar* Win2Bar(WINDOW win) { wxASSERT(win != NULL_WIN); return wxDynamicCast((wxObject*)win, TwxToolBar); } BOOLEAN xvt_toolbar_add_control(WINDOW win, int cid, TOOL_TYPE type, const char *title, int ico, int WXUNUSED(cust_width), int idx) { BOOLEAN ok = FALSE; TwxToolBar* ptb = Win2Bar(win); if (ptb != NULL) { TwxToolBar& tb = *ptb; switch (type) { case TOOL_SEPARATOR: #ifdef wxAuiToolBar tb.AddSeparator(); ok = idx < 0; #else if (idx < 0) ok = tb.AddSeparator() != NULL; else ok = tb.InsertSeparator(idx) != NULL; #endif break; default: { const wxBitmap& bmp = _GetToolResource(ico, tb.GetToolBitmapSize().y); wxString cap, tip; wxChar acc = 0; for (const char* t = title; *t; t++) { if (*t == '~' || *t == '&') { cap << '&'; acc = toupper(*(t+1)); } else { cap << *t; tip << *t; } } if (acc > '\0') { if (acc >= 'A' && acc <= 'Z') tip << "\n(Alt+" << acc << ")"; } else { switch (ico) // Gestione bottoni speciali { case 102: tip << "\n(Esc)"; break; case 114: tip << "\n(Alt+F4)"; break; case 162: tip << "\n(F2)"; break; case 163: tip << "\n(F1)"; break; default: break; } } #ifdef wxAuiToolBar tb.AddTool(cid, cap, bmp, wxNullBitmap, wxItemKind(type), tip, tip, NULL); ok = idx < 0; #else if (idx < 0) ok = tb.AddTool(cid, cap, bmp, wxNullBitmap, wxItemKind(type), tip) != NULL; else ok = tb.InsertTool(idx, cid, cap, bmp, wxNullBitmap, wxItemKind(type), tip) != NULL; #endif } break; } } return ok; } WINDOW xvt_toolbar_create(int cid, int left, int top, int right, int bottom, long nFlags, WINDOW parent) { #ifdef wxAuiToolBar long nStyle = wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_GRIPPER; if (nFlags & CTL_FLAG_PASSWORD) nStyle |= wxAUI_TB_TEXT; const wxPoint ptPos(left, top); wxSize szSize(right-left, bottom-top); int nIcoSize = 24; if (bottom > 0) { nIcoSize = RoundToIcon(szSize.y); } else { nStyle |= wxAUI_TB_VERTICAL; nIcoSize = RoundToIcon(szSize.x); } #else long nStyle = wxNO_BORDER | wxTB_NODIVIDER; if (nFlags & CTL_FLAG_PASSWORD) nStyle |= wxTB_TEXT | wxTB_FLAT; const wxPoint ptPos(left, top); wxSize szSize(right-left, bottom-top); int nIcoSize = 24; if (bottom > 0) { nStyle |= wxTB_HORIZONTAL; nIcoSize = RoundToIcon(szSize.y); } else { nStyle |= wxTB_VERTICAL; nIcoSize = RoundToIcon(szSize.x); } #endif wxWindow* pParent = wxStaticCast((wxObject*)parent, wxWindow); TwxToolBar* tb = new TwxToolBar(pParent, cid, ptPos, wxDefaultSize, nStyle); tb->SetToolBitmapSize(wxSize(nIcoSize, nIcoSize)); return (WINDOW)tb; } void xvt_toolbar_enable_control(WINDOW win, int cid, BOOLEAN on) { TwxToolBar* ptb = Win2Bar(win); if (ptb != NULL && cid > 0) ptb->EnableTool(cid, on != 0); } BOOLEAN xvt_toolbar_set_last_tool(WINDOW win, int id) { BOOLEAN bMoved = FALSE; TwxToolBar* ptb = Win2Bar(win); if (ptb != NULL) // Is a valid toolbar? { const int pos = ptb->GetToolPos(id); if (pos >= 0) { #ifdef wxAuiToolBar // TBI #else const int nCount = ptb->GetToolsCount(); if (pos < nCount-1) { wxToolBarToolBase* tool = ptb->RemoveTool(id); ptb->InsertTool(nCount-1, tool); } bMoved = TRUE; #endif } } return bMoved; } void xvt_toolbar_realize(WINDOW win) { TwxToolBar* ptb = Win2Bar(win); if (ptb != NULL) // Is a valid toolbar? { ptb->Realize(); // Update tools wxAuiPaneInfo* pi = LockPane(win); if (pi != NULL) { const wxSize szBar = ptb->GetSize(); if (pi->min_size.x < szBar.x || pi->min_size.y < szBar.y) { pi->MinSize(szBar); pi->BestSize(szBar); UnlockPane(win); } } // Iucunde repetita juvant: forzo il colore del gripper che viene spesso dimenticato wxAuiDockArt* pArtist = FindArtist(ptb); if (pArtist != NULL) pArtist->SetColor(wxAUI_DOCKART_GRIPPER_COLOUR, ptb->GetBackgroundColour()); } } void xvt_toolbar_show_control(WINDOW win, int cid, BOOLEAN on) { if (win != NULL_WIN && cid > 0) { wxASSERT(on);// Per ora non so come si faccia /* TwxToolBar* ptb = Win2Bar(win); if (ptb != NULL && cid > 0) { // ???? } */ } } // Funzione di utilita' un po' fuori posto (per poter accedere alla _GetToolResource) void xvt_dwin_draw_tool(WINDOW win, int x, int y, int rid, int size) { const wxBitmap& bmp = _GetToolResource(rid, size); if (bmp.IsOk()) { wxDC& dc = GetTDCMapper().GetDC(win); dc.DrawBitmap(bmp, x, y); } }