Files
wxWidgets/src/univ/combobox.cpp
Vadim Zeitlin b152d8c56c PCH-less compilation fix
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49016 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2007-10-02 11:32:25 +00:00

567 lines
15 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/univ/combobox.cpp
// Purpose: wxComboBox implementation
// Author: Vadim Zeitlin
// Modified by:
// Created: 15.12.00
// RCS-ID: $Id$
// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_COMBOBOX
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/button.h"
#include "wx/combobox.h"
#include "wx/listbox.h"
#include "wx/textctrl.h"
#include "wx/bmpbuttn.h"
#include "wx/validate.h"
#endif
#include "wx/tooltip.h"
#include "wx/combo.h"
#include "wx/univ/renderer.h"
#include "wx/univ/inphand.h"
#include "wx/univ/theme.h"
// ----------------------------------------------------------------------------
// wxStdComboBoxInputHandler: allows the user to open/close the combo from kbd
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxStdComboBoxInputHandler : public wxStdInputHandler
{
public:
wxStdComboBoxInputHandler(wxInputHandler *inphand);
virtual bool HandleKey(wxInputConsumer *consumer,
const wxKeyEvent& event,
bool pressed);
};
// ----------------------------------------------------------------------------
// wxComboListBox is a listbox modified to be used as a popup window in a
// combobox
// ----------------------------------------------------------------------------
class wxComboListBox : public wxListBox, public wxComboPopup
{
public:
// ctor and dtor
wxComboListBox();
virtual ~wxComboListBox();
// implement wxComboPopup methods
virtual bool Create(wxWindow* parent);
virtual void SetStringValue(const wxString& s);
virtual wxString GetStringValue() const;
virtual wxWindow *GetControl() { return this; }
virtual void OnPopup();
virtual wxSize GetAdjustedSize(int minWidth, int prefHeight, int maxHeight);
// fix virtual function hiding
virtual void SetSelection(int n) { DoSetSelection(n, true); }
void SetSelection(int n, bool select) { DoSetSelection(n, select); }
// used to process wxUniv actions
bool PerformAction(const wxControlAction& action,
long numArg,
const wxString& strArg);
protected:
// set m_clicked value from here
void OnLeftUp(wxMouseEvent& event);
private:
friend class wxComboBox; // it accesses our DoGetItemClientData()
DECLARE_EVENT_TABLE()
};
// ----------------------------------------------------------------------------
// event tables and such
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxComboListBox, wxListBox)
EVT_LEFT_UP(wxComboListBox::OnLeftUp)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS2(wxComboBox, wxControl, wxComboCtrl)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxComboListBox
// ----------------------------------------------------------------------------
wxComboListBox::wxComboListBox() : wxListBox(), wxComboPopup()
{
}
bool wxComboListBox::Create(wxWindow* parent)
{
if ( !wxListBox::Create(parent, wxID_ANY,
wxDefaultPosition, wxDefaultSize,
0, NULL,
wxBORDER_SIMPLE |
( m_combo->GetWindowStyle() & wxCB_SORT ? wxLB_SORT : 0 ) ) )
return false;
// we don't react to the mouse events outside the window at all
StopAutoScrolling();
return true;
}
wxComboListBox::~wxComboListBox()
{
}
wxString wxComboListBox::GetStringValue() const
{
return wxListBox::GetStringSelection();
}
void wxComboListBox::SetStringValue(const wxString& value)
{
if ( !value.empty() )
{
if (FindString(value) != wxNOT_FOUND)
wxListBox::SetStringSelection(value);
}
else
wxListBox::SetSelection(-1);
}
void wxComboListBox::OnPopup()
{
}
bool wxComboListBox::PerformAction(const wxControlAction& action,
long numArg,
const wxString& strArg)
{
if ( action == wxACTION_LISTBOX_FIND )
{
// we don't let the listbox handle this as instead of just using the
// single key presses, as usual, we use the text ctrl value as prefix
// and this is done by wxComboCtrl itself
return true;
}
return wxListBox::PerformAction(action, numArg, strArg);
}
void wxComboListBox::OnLeftUp(wxMouseEvent& event)
{
// we should dismiss the combo now
// first update the combo and close the listbox
Dismiss();
m_combo->SetValue(wxListBox::GetStringSelection());
// next let the user code have the event
wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId());
evt.SetInt(wxListBox::GetSelection());
evt.SetEventObject(m_combo);
m_combo->ProcessEvent(evt);
event.Skip();
}
wxSize wxComboListBox::GetAdjustedSize(int minWidth,
int WXUNUSED(prefHeight),
int maxHeight)
{
wxSize bestSize = wxListBox::GetBestSize();
return wxSize(wxMax(bestSize.x,minWidth),
wxMin(bestSize.y,maxHeight));
}
// ----------------------------------------------------------------------------
// wxComboBox
// ----------------------------------------------------------------------------
void wxComboBox::Init()
{
m_lbox = (wxListBox *)NULL;
}
wxComboBox::wxComboBox(wxWindow *parent,
wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString& name)
{
Init();
Create(parent, id, value, pos, size, choices, style, validator, name);
}
bool wxComboBox::Create(wxWindow *parent,
wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator,
const wxString& name)
{
wxCArrayString chs(choices);
return Create(parent, id, value, pos, size, chs.GetCount(),
chs.GetStrings(), style, validator, name);
}
bool wxComboBox::Create(wxWindow *parent,
wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
int n,
const wxString choices[],
long style,
const wxValidator& validator,
const wxString& name)
{
if ( !wxComboCtrl::Create(parent, id, value, pos, size, style,
validator, name) )
{
return false;
}
wxComboListBox *combolbox = new wxComboListBox();
SetPopupControl(combolbox);
m_lbox = combolbox;
m_lbox->Set(n, choices);
return true;
}
wxComboBox::~wxComboBox()
{
}
// ----------------------------------------------------------------------------
// wxComboBox methods forwarded to wxTextCtrl
// ----------------------------------------------------------------------------
wxString wxComboBox::GetValue() const
{
return wxComboCtrl::GetValue();
}
void wxComboBox::SetValue(const wxString& value)
{
wxComboCtrl::SetValue(value);
}
void wxComboBox::WriteText(const wxString& value)
{
if ( GetTextCtrl() ) GetTextCtrl()->WriteText(value);
}
void wxComboBox::Copy()
{
if ( GetTextCtrl() ) GetTextCtrl()->Copy();
}
void wxComboBox::Cut()
{
if ( GetTextCtrl() ) GetTextCtrl()->Cut();
}
void wxComboBox::Paste()
{
if ( GetTextCtrl() ) GetTextCtrl()->Paste();
}
void wxComboBox::SetInsertionPoint(long pos)
{
if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPoint(pos);
}
void wxComboBox::SetInsertionPointEnd()
{
if ( GetTextCtrl() ) GetTextCtrl()->SetInsertionPointEnd();
}
long wxComboBox::GetInsertionPoint() const
{
if ( GetTextCtrl() )
return GetTextCtrl()->GetInsertionPoint();
return -1;
}
wxTextPos wxComboBox::GetLastPosition() const
{
if ( GetTextCtrl() )
return GetTextCtrl()->GetLastPosition();
return -1;
}
void wxComboBox::Replace(long from, long to, const wxString& value)
{
if ( GetTextCtrl() ) GetTextCtrl()->Replace(from, to, value);
}
void wxComboBox::Remove(long from, long to)
{
if ( GetTextCtrl() ) GetTextCtrl()->Remove(from, to);
}
void wxComboBox::SetSelection(long from, long to)
{
if ( GetTextCtrl() ) GetTextCtrl()->SetSelection(from, to);
}
void wxComboBox::GetSelection(long *from, long *to) const
{
if ( GetTextCtrl() ) GetTextCtrl()->GetSelection(from, to);
}
void wxComboBox::SetEditable(bool editable)
{
if ( GetTextCtrl() ) GetTextCtrl()->SetEditable(editable);
}
// ----------------------------------------------------------------------------
// wxComboBox methods forwarded to wxListBox
// ----------------------------------------------------------------------------
void wxComboBox::DoClear()
{
GetLBox()->Clear();
if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
}
void wxComboBox::DoDeleteOneItem(unsigned int n)
{
wxCHECK_RET( IsValid(n), _T("invalid index in wxComboBox::Delete") );
if (GetSelection() == (int)n)
if ( GetTextCtrl() ) GetTextCtrl()->SetValue(wxEmptyString);
GetLBox()->Delete(n);
}
unsigned int wxComboBox::GetCount() const
{
return GetLBox()->GetCount();
}
wxString wxComboBox::GetString(unsigned int n) const
{
wxCHECK_MSG( IsValid(n), wxEmptyString, _T("invalid index in wxComboBox::GetString") );
return GetLBox()->GetString(n);
}
void wxComboBox::SetString(unsigned int n, const wxString& s)
{
wxCHECK_RET( IsValid(n), _T("invalid index in wxComboBox::SetString") );
GetLBox()->SetString(n, s);
}
int wxComboBox::FindString(const wxString& s, bool bCase) const
{
return GetLBox()->FindString(s, bCase);
}
void wxComboBox::SetSelection(int n)
{
wxCHECK_RET( (n == wxNOT_FOUND || IsValid(n)), _T("invalid index in wxComboBox::Select") );
GetLBox()->SetSelection(n);
wxString str;
if ( n != wxNOT_FOUND )
str = GetLBox()->GetString(n);
SetText(str);
}
int wxComboBox::GetSelection() const
{
#if 1 // FIXME:: What is the correct behavior?
// if the current value isn't one of the listbox strings, return -1
return GetLBox()->GetSelection();
#else
// Why oh why is this done this way?
// It is not because the value displayed in the text can be found
// in the list that it is the item that is selected!
return FindString(if ( GetTextCtrl() ) GetTextCtrl()->GetValue());
#endif
}
wxString wxComboBox::GetStringSelection() const
{
return GetLBox()->GetStringSelection();
}
wxClientDataType wxComboBox::GetClientDataType() const
{
return GetLBox()->GetClientDataType();
}
void wxComboBox::SetClientDataType(wxClientDataType clientDataItemsType)
{
GetLBox()->SetClientDataType(clientDataItemsType);
}
int wxComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
unsigned int pos,
void **clientData, wxClientDataType type)
{
return GetLBox()->DoInsertItems(items, pos, clientData, type);
}
void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
{
GetLBox()->DoSetItemClientData(n, clientData);
}
void *wxComboBox::DoGetItemClientData(unsigned int n) const
{
return GetLBox()->DoGetItemClientData(n);
}
bool wxComboBox::IsEditable() const
{
return GetTextCtrl() != NULL && (!HasFlag(wxCB_READONLY) || GetTextCtrl()->IsEditable() );
}
void wxComboBox::Undo()
{
if (IsEditable())
if ( GetTextCtrl() ) GetTextCtrl()->Undo();
}
void wxComboBox::Redo()
{
if (IsEditable())
if ( GetTextCtrl() ) GetTextCtrl()->Redo();
}
void wxComboBox::SelectAll()
{
if ( GetTextCtrl() ) GetTextCtrl()->SelectAll();
}
bool wxComboBox::CanCopy() const
{
if (GetTextCtrl() != NULL)
return GetTextCtrl()->CanCopy();
else
return false;
}
bool wxComboBox::CanCut() const
{
if (GetTextCtrl() != NULL)
return GetTextCtrl()->CanCut();
else
return false;
}
bool wxComboBox::CanPaste() const
{
if (IsEditable())
return GetTextCtrl()->CanPaste();
else
return false;
}
bool wxComboBox::CanUndo() const
{
if (IsEditable())
return GetTextCtrl()->CanUndo();
else
return false;
}
bool wxComboBox::CanRedo() const
{
if (IsEditable())
return GetTextCtrl()->CanRedo();
else
return false;
}
// ----------------------------------------------------------------------------
// wxStdComboBoxInputHandler
// ----------------------------------------------------------------------------
wxStdComboBoxInputHandler::wxStdComboBoxInputHandler(wxInputHandler *inphand)
: wxStdInputHandler(inphand)
{
}
bool wxStdComboBoxInputHandler::HandleKey(wxInputConsumer *consumer,
const wxKeyEvent& event,
bool pressed)
{
if ( pressed )
{
wxControlAction action;
switch ( event.GetKeyCode() )
{
case WXK_DOWN:
action = wxACTION_COMBOBOX_POPUP;
break;
case WXK_ESCAPE:
action = wxACTION_COMBOBOX_DISMISS;
break;
}
if ( !action.IsEmpty() )
{
consumer->PerformAction(action);
return true;
}
}
return wxStdInputHandler::HandleKey(consumer, event, pressed);
}
/* static */
wxInputHandler *wxComboBox::GetStdInputHandler(wxInputHandler *handlerDef)
{
static wxStdComboBoxInputHandler s_handler(handlerDef);
return &s_handler;
}
#endif // wxUSE_COMBOBOX