e7096e85d2
Just don't use bitmaps at all if SVG support is unavailable. Closes #22161.
1175 lines
37 KiB
C++
1175 lines
37 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: combo.cpp
|
|
// Purpose: wxComboCtrl sample
|
|
// Author: Jaakko Salli
|
|
// Modified by:
|
|
// Created: Apr-30-2006
|
|
// Copyright: (c) Jaakko Salli
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx/wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
|
|
// for all others, include the necessary headers (this file is usually all you
|
|
// need because it includes almost all "standard" wxWidgets headers)
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/wx.h"
|
|
#endif
|
|
|
|
#if !wxUSE_COMBOCTRL
|
|
#error "Please set wxUSE_COMBOCTRL to 1 and rebuild the library."
|
|
#endif
|
|
|
|
#include "wx/image.h"
|
|
|
|
#include "wx/combo.h"
|
|
#include "wx/odcombo.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// resources
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// the application icon (under Windows it is in resources and even
|
|
// though we could still include the XPM here it would be unused)
|
|
#ifndef wxHAS_IMAGES_IN_RESOURCES
|
|
#include "../sample.xpm"
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// private classes
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Define a new application type, each program should derive a class from wxApp
|
|
class MyApp : public wxApp
|
|
{
|
|
public:
|
|
// override base class virtuals
|
|
// ----------------------------
|
|
|
|
// this one is called on application startup and is a good place for the app
|
|
// initialization (doing it here and not in the ctor allows to have an error
|
|
// return: if OnInit() returns false, the application terminates)
|
|
virtual bool OnInit() wxOVERRIDE;
|
|
};
|
|
|
|
// Define a new frame type: this is going to be our main frame
|
|
class MyFrame : public wxFrame
|
|
{
|
|
public:
|
|
// ctor and dtor
|
|
MyFrame(const wxString& title);
|
|
~MyFrame();
|
|
|
|
// event handlers (these functions should _not_ be virtual)
|
|
void OnQuit(wxCommandEvent& event);
|
|
void OnAbout(wxCommandEvent& event);
|
|
|
|
void OnShowComparison( wxCommandEvent& event );
|
|
|
|
// log wxComboCtrl events
|
|
void OnComboBoxUpdate( wxCommandEvent& event );
|
|
|
|
void OnIdle( wxIdleEvent& event );
|
|
|
|
|
|
protected:
|
|
wxTextCtrl* m_logWin;
|
|
wxLog* m_logOld;
|
|
|
|
// Common list of items for all dialogs.
|
|
wxArrayString m_arrItems;
|
|
|
|
private:
|
|
// any class wishing to process wxWidgets events must use this macro
|
|
wxDECLARE_EVENT_TABLE();
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// constants
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// IDs for the controls and the menu commands
|
|
enum
|
|
{
|
|
ComboCtrl_Compare = wxID_HIGHEST,
|
|
|
|
// menu items
|
|
ComboCtrl_Quit = wxID_EXIT,
|
|
|
|
// it is important for the id corresponding to the "About" command to have
|
|
// this standard value as otherwise it won't be handled properly under Mac
|
|
// (where it is special and put into the "Apple" menu)
|
|
ComboCtrl_About = wxID_ABOUT
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// event tables and other macros for wxWidgets
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// the event tables connect the wxWidgets events with the functions (event
|
|
// handlers) which process them. It can be also done at run-time, but for the
|
|
// simple menu events like this the static method is much simpler.
|
|
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|
EVT_TEXT(wxID_ANY,MyFrame::OnComboBoxUpdate)
|
|
EVT_TEXT_ENTER(wxID_ANY,MyFrame::OnComboBoxUpdate)
|
|
EVT_COMBOBOX(wxID_ANY,MyFrame::OnComboBoxUpdate)
|
|
|
|
EVT_MENU(ComboCtrl_Compare, MyFrame::OnShowComparison)
|
|
EVT_MENU(ComboCtrl_Quit, MyFrame::OnQuit)
|
|
EVT_MENU(ComboCtrl_About, MyFrame::OnAbout)
|
|
|
|
EVT_IDLE(MyFrame::OnIdle)
|
|
wxEND_EVENT_TABLE()
|
|
|
|
// Create a new application object: this macro will allow wxWidgets to create
|
|
// the application object during program execution (it's better than using a
|
|
// static object for many reasons) and also implements the accessor function
|
|
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
|
|
// not wxApp)
|
|
wxIMPLEMENT_APP(MyApp);
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// the application class
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// 'Main program' equivalent: the program execution "starts" here
|
|
bool MyApp::OnInit()
|
|
{
|
|
if ( !wxApp::OnInit() )
|
|
return false;
|
|
|
|
// create the main application window
|
|
MyFrame *frame = new MyFrame("wxComboCtrl and wxOwnerDrawnComboBox Sample");
|
|
|
|
// and show it (the frames, unlike simple controls, are not shown when
|
|
// created initially)
|
|
frame->Show(true);
|
|
|
|
// success: wxApp::OnRun() will be called which will enter the main message
|
|
// loop and the application will run. If we returned false here, the
|
|
// application would exit immediately.
|
|
return true;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxOwnerDrawnComboBox with custom paint list items
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxPenStyleComboBox : public wxOwnerDrawnComboBox
|
|
{
|
|
public:
|
|
virtual void OnDrawItem( wxDC& dc,
|
|
const wxRect& rect,
|
|
int item,
|
|
int flags ) const wxOVERRIDE
|
|
{
|
|
if ( item == wxNOT_FOUND )
|
|
return;
|
|
|
|
wxRect r(rect);
|
|
r.Deflate(3);
|
|
r.height -= 2;
|
|
|
|
wxPenStyle penStyle = wxPENSTYLE_SOLID;
|
|
if ( item == 1 )
|
|
penStyle = wxPENSTYLE_TRANSPARENT;
|
|
else if ( item == 2 )
|
|
penStyle = wxPENSTYLE_DOT;
|
|
else if ( item == 3 )
|
|
penStyle = wxPENSTYLE_LONG_DASH;
|
|
else if ( item == 4 )
|
|
penStyle = wxPENSTYLE_SHORT_DASH;
|
|
else if ( item == 5 )
|
|
penStyle = wxPENSTYLE_DOT_DASH;
|
|
else if ( item == 6 )
|
|
penStyle = wxPENSTYLE_BDIAGONAL_HATCH;
|
|
else if ( item == 7 )
|
|
penStyle = wxPENSTYLE_CROSSDIAG_HATCH;
|
|
else if ( item == 8 )
|
|
penStyle = wxPENSTYLE_FDIAGONAL_HATCH;
|
|
else if ( item == 9 )
|
|
penStyle = wxPENSTYLE_CROSS_HATCH;
|
|
else if ( item == 10 )
|
|
penStyle = wxPENSTYLE_HORIZONTAL_HATCH;
|
|
else if ( item == 11 )
|
|
penStyle = wxPENSTYLE_VERTICAL_HATCH;
|
|
|
|
wxPen pen( dc.GetTextForeground(), 3, penStyle );
|
|
|
|
// Get text colour as pen colour
|
|
dc.SetPen( pen );
|
|
|
|
if ( !(flags & wxODCB_PAINTING_CONTROL) )
|
|
{
|
|
dc.DrawText(GetString( item ),
|
|
r.x + 3,
|
|
(r.y + 0) + ( (r.height/2) - dc.GetCharHeight() )/2
|
|
);
|
|
|
|
dc.DrawLine( r.x+5, r.y+((r.height/4)*3), r.x+r.width - 5, r.y+((r.height/4)*3) );
|
|
}
|
|
else
|
|
{
|
|
dc.DrawLine( r.x+5, r.y+r.height/2, r.x+r.width - 5, r.y+r.height/2 );
|
|
}
|
|
}
|
|
|
|
virtual void OnDrawBackground( wxDC& dc, const wxRect& rect,
|
|
int item, int flags ) const wxOVERRIDE
|
|
{
|
|
|
|
// If item is selected or even, or we are painting the
|
|
// combo control itself, use the default rendering.
|
|
if ( (flags & (wxODCB_PAINTING_CONTROL|wxODCB_PAINTING_SELECTED)) ||
|
|
(item & 1) == 0 )
|
|
{
|
|
wxOwnerDrawnComboBox::OnDrawBackground(dc,rect,item,flags);
|
|
return;
|
|
}
|
|
|
|
// Otherwise, draw every other background with different colour.
|
|
wxColour bgCol(240,240,250);
|
|
dc.SetBrush(wxBrush(bgCol));
|
|
dc.SetPen(wxPen(bgCol));
|
|
dc.DrawRectangle(rect);
|
|
}
|
|
|
|
virtual wxCoord OnMeasureItem( size_t item ) const wxOVERRIDE
|
|
{
|
|
// Simply demonstrate the ability to have variable-height items
|
|
return FromDIP( item & 1 ? 36 : 24 );
|
|
}
|
|
|
|
virtual wxCoord OnMeasureItemWidth( size_t WXUNUSED(item) ) const wxOVERRIDE
|
|
{
|
|
return -1; // default - will be measured from text width
|
|
}
|
|
|
|
};
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxListView Custom popup interface
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "wx/listctrl.h"
|
|
|
|
class ListViewComboPopup : public wxListView, public wxComboPopup
|
|
{
|
|
public:
|
|
|
|
virtual void Init() wxOVERRIDE
|
|
{
|
|
m_value = -1;
|
|
m_itemHere = -1; // hot item in list
|
|
}
|
|
|
|
virtual bool Create( wxWindow* parent ) wxOVERRIDE
|
|
{
|
|
return wxListView::Create(parent,1,
|
|
wxPoint(0,0),wxDefaultSize,
|
|
wxLC_LIST|wxLC_SINGLE_SEL|
|
|
wxLC_SORT_ASCENDING|wxSIMPLE_BORDER);
|
|
}
|
|
|
|
virtual wxWindow *GetControl() wxOVERRIDE { return this; }
|
|
|
|
virtual void SetStringValue( const wxString& s ) wxOVERRIDE
|
|
{
|
|
int n = wxListView::FindItem(-1,s);
|
|
if ( n >= 0 && n < GetItemCount() )
|
|
wxListView::Select(n);
|
|
}
|
|
|
|
virtual wxString GetStringValue() const wxOVERRIDE
|
|
{
|
|
if ( m_value >= 0 )
|
|
return wxListView::GetItemText(m_value);
|
|
return wxEmptyString;
|
|
}
|
|
|
|
//
|
|
// Popup event handlers
|
|
//
|
|
|
|
// Mouse hot-tracking
|
|
void OnMouseMove(wxMouseEvent& event)
|
|
{
|
|
// Move selection to cursor if it is inside the popup
|
|
|
|
int resFlags;
|
|
int itemHere = HitTest(event.GetPosition(),resFlags);
|
|
if ( itemHere >= 0 )
|
|
{
|
|
wxListView::Select(itemHere,true);
|
|
m_itemHere = itemHere;
|
|
}
|
|
event.Skip();
|
|
}
|
|
|
|
// On mouse left, set the value and close the popup
|
|
void OnMouseClick(wxMouseEvent& WXUNUSED(event))
|
|
{
|
|
m_value = m_itemHere;
|
|
// TODO: Send event
|
|
Dismiss();
|
|
}
|
|
|
|
//
|
|
// Utilities for item manipulation
|
|
//
|
|
|
|
void AddSelection( const wxString& selstr )
|
|
{
|
|
wxListView::InsertItem(GetItemCount(),selstr);
|
|
}
|
|
|
|
protected:
|
|
|
|
int m_value; // current item index
|
|
int m_itemHere; // hot item in popup
|
|
|
|
private:
|
|
wxDECLARE_EVENT_TABLE();
|
|
};
|
|
|
|
wxBEGIN_EVENT_TABLE(ListViewComboPopup, wxListView)
|
|
EVT_MOTION(ListViewComboPopup::OnMouseMove)
|
|
// NOTE: Left down event is used instead of left up right now
|
|
// since MSW wxListCtrl doesn't seem to emit left ups
|
|
// consistently.
|
|
EVT_LEFT_DOWN(ListViewComboPopup::OnMouseClick)
|
|
wxEND_EVENT_TABLE()
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxTreeCtrl Custom popup interface
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "wx/treectrl.h"
|
|
|
|
class TreeCtrlComboPopup : public wxTreeCtrl, public wxComboPopup
|
|
{
|
|
public:
|
|
|
|
virtual void Init() wxOVERRIDE
|
|
{
|
|
}
|
|
virtual ~TreeCtrlComboPopup()
|
|
{
|
|
if (!m_isBeingDeleted)
|
|
{
|
|
wxMessageBox("error wxTreeCtrl::Destroy() was not called");
|
|
}
|
|
SendDestroyEvent();
|
|
}
|
|
|
|
virtual bool Create( wxWindow* parent ) wxOVERRIDE
|
|
{
|
|
return wxTreeCtrl::Create(parent,1,
|
|
wxPoint(0,0),wxDefaultSize,
|
|
wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT | wxSIMPLE_BORDER );
|
|
}
|
|
|
|
virtual void OnShow()
|
|
{
|
|
// make sure selected item is visible
|
|
if ( m_value.IsOk() )
|
|
EnsureVisible(m_value);
|
|
}
|
|
|
|
virtual wxSize GetAdjustedSize( int minWidth,
|
|
int WXUNUSED(prefHeight),
|
|
int maxHeight ) wxOVERRIDE
|
|
{
|
|
return wxSize(wxMax(300,minWidth),wxMin(250,maxHeight));
|
|
}
|
|
|
|
virtual wxWindow *GetControl() wxOVERRIDE { return this; }
|
|
|
|
// Needed by SetStringValue
|
|
wxTreeItemId FindItemByText( wxTreeItemId parent, const wxString& text )
|
|
{
|
|
wxTreeItemIdValue cookie;
|
|
wxTreeItemId child = GetFirstChild(parent,cookie);
|
|
while ( child.IsOk() )
|
|
{
|
|
if ( GetItemText(child) == text )
|
|
{
|
|
return child;
|
|
}
|
|
if ( ItemHasChildren(child) )
|
|
{
|
|
wxTreeItemId found = FindItemByText(child,text);
|
|
if ( found.IsOk() )
|
|
return found;
|
|
}
|
|
child = GetNextChild(parent,cookie);
|
|
}
|
|
return wxTreeItemId();
|
|
}
|
|
|
|
virtual void SetStringValue( const wxString& s ) wxOVERRIDE
|
|
{
|
|
wxTreeItemId root = GetRootItem();
|
|
if ( !root.IsOk() )
|
|
return;
|
|
|
|
wxTreeItemId found = FindItemByText(root,s);
|
|
if ( found.IsOk() )
|
|
{
|
|
m_value = m_itemHere = found;
|
|
wxTreeCtrl::SelectItem(found);
|
|
}
|
|
}
|
|
|
|
virtual wxString GetStringValue() const wxOVERRIDE
|
|
{
|
|
if ( m_value.IsOk() )
|
|
return wxTreeCtrl::GetItemText(m_value);
|
|
return wxEmptyString;
|
|
}
|
|
|
|
//
|
|
// Popup event handlers
|
|
//
|
|
|
|
// Mouse hot-tracking
|
|
void OnMouseMove(wxMouseEvent& event)
|
|
{
|
|
int resFlags;
|
|
wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
|
|
if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
|
|
{
|
|
wxTreeCtrl::SelectItem(itemHere,true);
|
|
m_itemHere = itemHere;
|
|
}
|
|
event.Skip();
|
|
}
|
|
|
|
// On mouse left, set the value and close the popup
|
|
void OnMouseClick(wxMouseEvent& event)
|
|
{
|
|
int resFlags;
|
|
wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
|
|
if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
|
|
{
|
|
m_itemHere = itemHere;
|
|
m_value = itemHere;
|
|
Dismiss();
|
|
// TODO: Send event
|
|
}
|
|
event.Skip();
|
|
}
|
|
|
|
protected:
|
|
|
|
wxTreeItemId m_value; // current item index
|
|
wxTreeItemId m_itemHere; // hot item in popup
|
|
|
|
private:
|
|
wxDECLARE_EVENT_TABLE();
|
|
};
|
|
|
|
wxBEGIN_EVENT_TABLE(TreeCtrlComboPopup, wxTreeCtrl)
|
|
EVT_MOTION(TreeCtrlComboPopup::OnMouseMove)
|
|
// NOTE: Left down event is used instead of left up right now
|
|
// since MSW wxTreeCtrl doesn't seem to emit left ups
|
|
// consistently.
|
|
EVT_LEFT_DOWN(TreeCtrlComboPopup::OnMouseClick)
|
|
wxEND_EVENT_TABLE()
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxComboCtrl with custom popup animation, using wxWindow::ShowWithEffect().
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxComboCtrlWithCustomPopupAnim : public wxComboCtrl
|
|
{
|
|
protected:
|
|
virtual bool AnimateShow( const wxRect& rect, int WXUNUSED(flags) ) wxOVERRIDE
|
|
{
|
|
wxWindow* win = GetPopupWindow();
|
|
win->SetSize(rect);
|
|
win->Raise(); // This is needed
|
|
win->ShowWithEffect(wxSHOW_EFFECT_BLEND);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxComboCtrl with entirely custom button action (opens file dialog)
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxFileSelectorCombo : public wxComboCtrl
|
|
{
|
|
public:
|
|
wxFileSelectorCombo() : wxComboCtrl() { Init(); }
|
|
|
|
wxFileSelectorCombo(wxWindow *parent,
|
|
wxWindowID id = wxID_ANY,
|
|
const wxString& value = wxEmptyString,
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
const wxSize& size = wxDefaultSize,
|
|
long style = 0,
|
|
const wxValidator& validator = wxDefaultValidator,
|
|
const wxString& name = wxComboBoxNameStr)
|
|
: wxComboCtrl()
|
|
{
|
|
Init();
|
|
Create(parent,id,value,
|
|
pos,size,
|
|
// Style flag wxCC_STD_BUTTON makes the button
|
|
// behave more like a standard push button.
|
|
style | wxCC_STD_BUTTON,
|
|
validator,name);
|
|
|
|
#ifdef wxHAS_SVG
|
|
SetButtonBitmaps(wxBitmapBundle::FromSVGFile("three-dots.svg", wxSize(16, 16)), true);
|
|
#endif
|
|
}
|
|
|
|
virtual void OnButtonClick() wxOVERRIDE
|
|
{
|
|
// Show standard wxFileDialog on button click
|
|
|
|
wxFileDialog dlg(this,
|
|
"Choose File",
|
|
wxEmptyString,
|
|
GetValue(),
|
|
"All files (*.*)|*.*",
|
|
wxFD_OPEN);
|
|
|
|
if ( dlg.ShowModal() == wxID_OK )
|
|
{
|
|
SetValue(dlg.GetPath());
|
|
}
|
|
}
|
|
|
|
// Implement empty DoSetPopupControl to prevent assertion failure.
|
|
virtual void DoSetPopupControl(wxComboPopup* WXUNUSED(popup)) wxOVERRIDE
|
|
{
|
|
}
|
|
|
|
private:
|
|
void Init()
|
|
{
|
|
// Initialize member variables here
|
|
}
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// main frame
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// frame constructor
|
|
MyFrame::MyFrame(const wxString& title)
|
|
: wxFrame(NULL, wxID_ANY, title)
|
|
{
|
|
wxBoxSizer* topSizer;
|
|
wxBoxSizer* topRowSizer;
|
|
wxBoxSizer* colSizer;
|
|
wxBoxSizer* rowSizer;
|
|
|
|
// set the frame icon
|
|
SetIcon(wxICON(sample));
|
|
|
|
#if wxUSE_MENUS
|
|
// create a menu bar
|
|
wxMenu *fileMenu = new wxMenu;
|
|
|
|
// the "About" item should be in the help menu
|
|
wxMenu *helpMenu = new wxMenu;
|
|
helpMenu->Append(ComboCtrl_About, "&About\tF1", "Show about dialog");
|
|
|
|
fileMenu->Append(ComboCtrl_Compare, "&Compare against wxComboBox...",
|
|
"Show some wxOwnerDrawnComboBoxes side-by-side with native wxComboBoxes.");
|
|
fileMenu->AppendSeparator();
|
|
fileMenu->Append(ComboCtrl_Quit, "E&xit\tAlt-X", "Quit this program");
|
|
|
|
// now append the freshly created menu to the menu bar...
|
|
wxMenuBar *menuBar = new wxMenuBar();
|
|
menuBar->Append(fileMenu, "&File");
|
|
menuBar->Append(helpMenu, "&Help");
|
|
|
|
// ... and attach this menu bar to the frame
|
|
SetMenuBar(menuBar);
|
|
#endif // wxUSE_MENUS
|
|
|
|
wxPanel* panel = new wxPanel(this);
|
|
|
|
// Prepare log window right away since it shows EVT_TEXTs
|
|
m_logWin = new wxTextCtrl(panel, 105, wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxSize(-1, 125),
|
|
wxTE_MULTILINE);
|
|
wxLogTextCtrl* logger = new wxLogTextCtrl(m_logWin);
|
|
m_logOld = logger->SetActiveTarget(logger);
|
|
logger->DisableTimestamp();
|
|
|
|
|
|
topSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
topRowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
|
|
colSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
|
|
wxComboCtrl* cc;
|
|
wxGenericComboCtrl* gcc;
|
|
wxOwnerDrawnComboBox* odc;
|
|
|
|
// Create common strings array
|
|
m_arrItems.Add( "Solid" );
|
|
m_arrItems.Add( "Transparent" );
|
|
m_arrItems.Add( "Dot" );
|
|
m_arrItems.Add( "Long Dash" );
|
|
m_arrItems.Add( "Short Dash" );
|
|
m_arrItems.Add( "Dot Dash" );
|
|
m_arrItems.Add( "Backward Diagonal Hatch" );
|
|
m_arrItems.Add( "Cross-diagonal Hatch" );
|
|
m_arrItems.Add( "Forward Diagonal Hatch" );
|
|
m_arrItems.Add( "Cross Hatch" );
|
|
m_arrItems.Add( "Horizontal Hatch" );
|
|
m_arrItems.Add( "Vertical Hatch" );
|
|
|
|
|
|
//
|
|
// Create pen selector ODComboBox with owner-drawn items
|
|
//
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
rowSizer->Add( new wxStaticText(panel,wxID_ANY,
|
|
"OwnerDrawnComboBox with owner-drawn items:"), 1,
|
|
wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
|
|
|
|
// When defining derivative class for callbacks, we need
|
|
// to use two-stage creation (or redefine the common wx
|
|
// constructor).
|
|
odc = new wxPenStyleComboBox();
|
|
odc->Create(panel,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
|
|
);
|
|
|
|
|
|
odc->SetSelection(0);
|
|
|
|
rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
|
rowSizer->AddStretchSpacer(1);
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
|
|
|
|
//
|
|
// Same but with changed button position
|
|
//
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
rowSizer->Add( new wxStaticText(panel,wxID_ANY,
|
|
"OwnerDrawnComboBox with owner-drawn items and button on the left:"), 1,
|
|
wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
|
|
|
|
// When defining derivative class for callbacks, we need
|
|
// to use two-stage creation (or redefine the common wx
|
|
// constructor).
|
|
odc = new wxPenStyleComboBox();
|
|
odc->Create(panel,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
|
|
);
|
|
|
|
|
|
odc->SetSelection(0);
|
|
|
|
// Use button size that is slightly smaller than the default.
|
|
wxSize butSize = odc->GetButtonSize();
|
|
odc->SetButtonPosition(butSize.x - 2, // button width
|
|
butSize.y - 6, // button height
|
|
wxLEFT, // side
|
|
2 // horizontal spacing
|
|
);
|
|
|
|
rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
|
rowSizer->AddStretchSpacer(1);
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
|
|
//
|
|
// List View wxComboCtrl
|
|
//
|
|
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
rowSizer->Add( new wxStaticText(panel,
|
|
wxID_ANY,
|
|
"List View wxComboCtrl (custom animation):"),
|
|
1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
|
|
rowSizer->Add( new wxStaticText(panel,wxID_ANY,"Tree Ctrl wxComboCtrl:"), 1,
|
|
wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
cc = new wxComboCtrlWithCustomPopupAnim();
|
|
|
|
// Let's set a custom style for the contained wxTextCtrl. We need to
|
|
// use two-step creation for it to work properly.
|
|
cc->SetTextCtrlStyle(wxTE_RIGHT);
|
|
|
|
cc->Create(panel, wxID_ANY, wxEmptyString);
|
|
|
|
// Make sure we use popup that allows focusing the listview.
|
|
cc->UseAltPopupWindow();
|
|
|
|
cc->SetPopupMinWidth(300);
|
|
|
|
ListViewComboPopup* iface = new ListViewComboPopup();
|
|
cc->SetPopupControl(iface);
|
|
|
|
int i;
|
|
for ( i=0; i<100; i++ )
|
|
iface->AddSelection( wxString::Format("Item %02i",i));
|
|
|
|
rowSizer->Add( cc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
|
|
|
|
|
//
|
|
// Tree Ctrl wxComboCtrl
|
|
//
|
|
|
|
// Note that we test that wxGenericComboCtrl works
|
|
gcc = new wxGenericComboCtrl(panel,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize);
|
|
|
|
// Make sure we use popup that allows focusing the treectrl.
|
|
gcc->UseAltPopupWindow();
|
|
|
|
// Set popup interface right away, otherwise some of the calls
|
|
// below may fail
|
|
TreeCtrlComboPopup* tcPopup = new TreeCtrlComboPopup();
|
|
gcc->SetPopupControl(tcPopup);
|
|
|
|
// Add items using wxTreeCtrl methods directly
|
|
wxTreeItemId rootId = tcPopup->AddRoot("<hidden_root>");
|
|
|
|
wxTreeItemId groupId;
|
|
|
|
for ( i=0; i<4; i++ )
|
|
{
|
|
groupId = tcPopup->AppendItem(rootId,
|
|
wxString::Format("Branch %02i",i));
|
|
|
|
int n;
|
|
for ( n=0; n<25; n++ )
|
|
tcPopup->AppendItem(groupId,
|
|
wxString::Format("Subitem %02i",(i*25)+n));
|
|
}
|
|
|
|
gcc->SetValue("Subitem 05");
|
|
|
|
// Move button to left - it makes more sense for a tree ctrl
|
|
gcc->SetButtonPosition(-1, // button width
|
|
-1, // button height
|
|
wxLEFT, // side
|
|
0 // horizontal spacing
|
|
);
|
|
|
|
rowSizer->Add( gcc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
|
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
#if wxUSE_IMAGE
|
|
wxInitAllImageHandlers();
|
|
|
|
//
|
|
// Custom Dropbutton Bitmaps
|
|
// (second one uses blank button background)
|
|
//
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
rowSizer->Add( new wxStaticText(panel,wxID_ANY,
|
|
"OwnerDrawnComboBox with simple dropbutton graphics:"), 1,
|
|
wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
|
|
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
|
|
odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
(long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
|
|
);
|
|
|
|
wxOwnerDrawnComboBox* odc2;
|
|
odc2 = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
(long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
|
|
);
|
|
|
|
// Load images from disk
|
|
#ifdef wxHAS_SVG
|
|
wxBitmapBundle bmpNormal = wxBitmapBundle::FromSVGFile("dropbutn.svg", wxSize(16, 16));
|
|
wxBitmapBundle bmpPressed = wxBitmapBundle::FromSVGFile("dropbutp.svg", wxSize(16, 16));
|
|
wxBitmapBundle bmpHover = wxBitmapBundle::FromSVGFile("dropbuth.svg", wxSize(16, 16));
|
|
|
|
if ( bmpNormal.IsOk() && bmpPressed.IsOk() && bmpHover.IsOk() )
|
|
{
|
|
odc->SetButtonBitmaps(bmpNormal, false, bmpPressed, bmpHover);
|
|
odc2->SetButtonBitmaps(bmpNormal, true, bmpPressed, bmpHover);
|
|
}
|
|
else
|
|
wxLogError("Dropbutton images not found");
|
|
#endif
|
|
|
|
//odc2->SetButtonPosition(0, // width adjustment
|
|
// 0, // height adjustment
|
|
// wxLEFT, // side
|
|
// 0 // horizontal spacing
|
|
// );
|
|
|
|
rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
|
rowSizer->Add( odc2, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
#endif
|
|
|
|
|
|
//
|
|
// wxComboCtrl with totally custom button action (open file dialog)
|
|
//
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
rowSizer->Add( new wxStaticText(panel,wxID_ANY,
|
|
"wxComboCtrl with custom button and custom main control:"), 1,
|
|
wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
|
|
|
|
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
|
wxFileSelectorCombo* fsc;
|
|
|
|
fsc = new wxFileSelectorCombo(panel,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
(long)0
|
|
);
|
|
|
|
// This is a perfectly useless control, as the popup and main control
|
|
// don't interact with each other, but it shows that we can use something
|
|
// other than wxTextCtrl for the main part of wxComboCtrl too.
|
|
//
|
|
// In a real program, custom popup and main control would work together,
|
|
// i.e. changing selection in one of them would update the other one.
|
|
//
|
|
// Also note the complicated dance we need to go through to create the
|
|
// controls in the right order: we want to create the custom main control
|
|
// before actually creating the wxComboCtrl window, as otherwise it would
|
|
// unnecessarily create a wxTextCtrl by default, forcing us to use its
|
|
// default ctor and Create() later, but this, in turn, also requires using
|
|
// default ctor for the main control and creating it later too, as it can't
|
|
// be created before its parent window is.
|
|
wxComboCtrl* comboCustom = new wxComboCtrl();
|
|
wxCheckBox* cbox = new wxCheckBox();
|
|
comboCustom->SetMainControl(cbox);
|
|
comboCustom->Create(panel, wxID_ANY, wxEmptyString);
|
|
cbox->Create(comboCustom, wxID_ANY, "Checkbox as main control");
|
|
cbox->SetBackgroundColour(*wxWHITE);
|
|
|
|
comboCustom->SetPopupControl(new ListViewComboPopup());
|
|
|
|
rowSizer->Add( fsc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
|
rowSizer->Add( comboCustom, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
|
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
|
|
|
|
|
// Make sure GetFeatures is implemented
|
|
wxComboCtrl::GetFeatures();
|
|
|
|
|
|
topRowSizer->Add( colSizer, 1, wxALL, 2 );
|
|
|
|
colSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
colSizer->AddSpacer(8);
|
|
colSizer->Add( new wxStaticText(panel, wxID_ANY, "Log Messages:"), 0, wxTOP|wxLEFT, 3 );
|
|
colSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 3 );
|
|
|
|
topRowSizer->Add( colSizer, 1, wxEXPAND|wxALL, 2 );
|
|
topSizer->Add( topRowSizer, 1, wxEXPAND );
|
|
|
|
panel->SetSizer( topSizer );
|
|
topSizer->SetSizeHints( panel );
|
|
|
|
Fit();
|
|
Centre();
|
|
}
|
|
|
|
// event handlers
|
|
|
|
void MyFrame::OnComboBoxUpdate( wxCommandEvent& event )
|
|
{
|
|
// Don't show messages for the log output window (it'll crash)
|
|
if ( !event.GetEventObject()->IsKindOf(CLASSINFO(wxComboCtrl)) )
|
|
return;
|
|
|
|
if ( event.GetEventType() == wxEVT_COMBOBOX )
|
|
{
|
|
wxLogMessage("EVT_COMBOBOX(id=%i,selection=%i)",event.GetId(),event.GetSelection());
|
|
}
|
|
else if ( event.GetEventType() == wxEVT_TEXT )
|
|
{
|
|
wxLogMessage("EVT_TEXT(id=%i,string=\"%s\")",event.GetId(),event.GetString());
|
|
}
|
|
else if ( event.GetEventType() == wxEVT_TEXT_ENTER )
|
|
{
|
|
wxLogMessage("EVT_TEXT_ENTER(id=%i,string=\"%s\")",
|
|
event.GetId(), event.GetString());
|
|
}
|
|
}
|
|
|
|
void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
|
|
{
|
|
//
|
|
// Show some wxOwnerDrawComboBoxes for comparison
|
|
//
|
|
|
|
wxBoxSizer* colSizer;
|
|
wxBoxSizer* rowSizer;
|
|
wxStaticBoxSizer* groupSizer;
|
|
|
|
wxComboBox* cb;
|
|
wxOwnerDrawnComboBox* odc;
|
|
|
|
const int border = 4;
|
|
|
|
wxDialog* dlg = new wxDialog(this,wxID_ANY,
|
|
"Compare against wxComboBox",
|
|
wxDefaultPosition,wxDefaultSize,
|
|
wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
|
|
|
|
colSizer = new wxBoxSizer( wxVERTICAL );
|
|
|
|
rowSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY," wxOwnerDrawnComboBox "),
|
|
wxVERTICAL);
|
|
|
|
groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
|
|
"Writable, with margins, sorted:"),
|
|
wxSizerFlags().Expand().Border(wxRIGHT, border) );
|
|
|
|
odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_SORT // wxNO_BORDER|wxCB_READONLY
|
|
);
|
|
|
|
odc->Append("H - Appended Item"); // test sorting in append
|
|
|
|
odc->SetValue("Dot Dash");
|
|
odc->SetMargins(15, 10);
|
|
groupSizer->Add( odc, wxSizerFlags().Border(wxALL, border) );
|
|
groupSizer->AddStretchSpacer();
|
|
|
|
//
|
|
// Readonly ODComboBox
|
|
groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
|
|
"Read-only, big font:"),
|
|
wxSizerFlags().Border(wxRIGHT, border) );
|
|
|
|
odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
|
|
);
|
|
|
|
odc->SetFont(odc->GetFont().Scale(1.5));
|
|
odc->SetValue("Dot Dash");
|
|
odc->SetText("Dot Dash (Testing SetText)");
|
|
|
|
groupSizer->Add( odc, 0, wxALL, border );
|
|
groupSizer->AddStretchSpacer();
|
|
|
|
//
|
|
// Disabled read-only ODComboBox
|
|
groupSizer->Add( new wxStaticText(dlg,wxID_ANY,"Read-only disabled:"),
|
|
wxSizerFlags().Border(wxRIGHT, border) );
|
|
|
|
odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
|
|
);
|
|
|
|
odc->SetValue("Dot Dash");
|
|
odc->Enable(false);
|
|
|
|
groupSizer->Add( odc, wxSizerFlags(3).Expand().Border(wxALL, border) );
|
|
|
|
// Disabled ODComboBox
|
|
groupSizer->Add(new wxStaticText(dlg, wxID_ANY, "Disabled:"),
|
|
wxSizerFlags().Border(wxRIGHT, border));
|
|
|
|
odc = new wxOwnerDrawnComboBox(dlg, wxID_ANY, wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize, m_arrItems);
|
|
|
|
odc->SetValue("Dot Dash");
|
|
odc->Enable(false);
|
|
|
|
groupSizer->Add(odc, wxSizerFlags(3).Expand().Border(wxALL, border));
|
|
|
|
rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
|
|
|
|
|
|
groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY," wxComboBox "),
|
|
wxVERTICAL);
|
|
|
|
//
|
|
// wxComboBox
|
|
//
|
|
groupSizer->Add( new wxStaticText(dlg,wxID_ANY,
|
|
"Writable, with margins, sorted:"),
|
|
wxSizerFlags().Expand().Border(wxRIGHT, border) );
|
|
|
|
cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_SORT // wxNO_BORDER|wxCB_READONLY
|
|
);
|
|
|
|
cb->Append("H - Appended Item"); // test sorting in append
|
|
|
|
cb->SetValue("Dot Dash");
|
|
cb->SetMargins(15, 10);
|
|
groupSizer->Add( cb, wxSizerFlags().Border(wxALL, border) );
|
|
groupSizer->AddStretchSpacer();
|
|
|
|
//
|
|
// Readonly wxComboBox
|
|
groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
|
|
"Read-only, big font:"),
|
|
wxSizerFlags().Border(wxRIGHT, border) );
|
|
|
|
cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
|
|
);
|
|
|
|
cb->SetFont(cb->GetFont().Scale(1.5));
|
|
cb->SetValue("Dot Dash");
|
|
|
|
groupSizer->Add( cb, 0, wxALL, border );
|
|
groupSizer->AddStretchSpacer();
|
|
|
|
//
|
|
// Disabled read-only wxComboBox
|
|
groupSizer->Add( new wxStaticText(dlg,wxID_ANY,"Read-only disabled:"),
|
|
wxSizerFlags().Border(wxRIGHT, border) );
|
|
|
|
cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize,
|
|
m_arrItems,
|
|
wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
|
|
);
|
|
|
|
cb->SetValue("Dot Dash");
|
|
cb->Enable(false);
|
|
|
|
groupSizer->Add( cb, wxSizerFlags(3).Expand().Border(wxALL, border) );
|
|
|
|
//
|
|
// Disabled wxComboBox
|
|
groupSizer->Add(new wxStaticText(dlg, wxID_ANY, "Disabled:"),
|
|
wxSizerFlags().Border(wxRIGHT, border));
|
|
|
|
cb = new wxComboBox(dlg, wxID_ANY, wxEmptyString,
|
|
wxDefaultPosition, wxDefaultSize, m_arrItems);
|
|
|
|
cb->SetValue("Dot Dash");
|
|
cb->Enable(false);
|
|
|
|
groupSizer->Add(cb, wxSizerFlags(3).Expand().Border(wxALL, border));
|
|
|
|
rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
|
|
|
|
colSizer->Add( rowSizer, 1, wxEXPAND|wxALL, border );
|
|
|
|
dlg->SetSizer( colSizer );
|
|
colSizer->SetSizeHints( dlg );
|
|
|
|
dlg->SetSize(60,240);
|
|
dlg->Centre();
|
|
dlg->ShowModal();
|
|
}
|
|
|
|
MyFrame::~MyFrame()
|
|
{
|
|
delete wxLog::SetActiveTarget(m_logOld);
|
|
}
|
|
|
|
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
|
{
|
|
// true is to force the frame to close
|
|
Close(true);
|
|
}
|
|
|
|
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
|
{
|
|
wxMessageBox(wxString::Format(
|
|
"Welcome to %s!\n"
|
|
"\n"
|
|
"This is the wxWidgets wxComboCtrl and wxOwnerDrawnComboBox sample\n"
|
|
"running under %s.",
|
|
wxVERSION_STRING,
|
|
wxGetOsDescription()
|
|
),
|
|
"About wxComboCtrl sample",
|
|
wxOK | wxICON_INFORMATION,
|
|
this);
|
|
}
|
|
|
|
void MyFrame::OnIdle(wxIdleEvent& event)
|
|
{
|
|
// This code is useful for debugging focus problems
|
|
// (which are plentiful when dealing with popup windows).
|
|
#if 0
|
|
static wxWindow* lastFocus = (wxWindow*) NULL;
|
|
|
|
wxWindow* curFocus = ::wxWindow::FindFocus();
|
|
|
|
if ( curFocus != lastFocus )
|
|
{
|
|
const wxChar* className = "<none>";
|
|
if ( curFocus )
|
|
className = curFocus->GetClassInfo()->GetClassName();
|
|
lastFocus = curFocus;
|
|
wxLogDebug( "FOCUSED: %s %X",
|
|
className,
|
|
(unsigned int)curFocus);
|
|
}
|
|
#endif
|
|
|
|
event.Skip();
|
|
}
|