Files
wxWidgets/src/msw/checklst.cpp
Vadim Zeitlin 3f66f6a5b3 Remove all lines containing cvs/svn "$Id$" keyword.
This keyword is not expanded by Git which means it's not replaced with the
correct revision value in the releases made using git-based scripts and it's
confusing to have lines with unexpanded "$Id$" in the released files. As
expanding them with Git is not that simple (it could be done with git archive
and export-subst attribute) and there are not many benefits in having them in
the first place, just remove all these lines.

If nothing else, this will make an eventual transition to Git simpler.

Closes #14487.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-07-26 16:02:46 +00:00

435 lines
12 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/msw/checklst.cpp
// Purpose: implementation of wxCheckListBox class
// Author: Vadim Zeitlin
// Modified by:
// Created: 16.11.97
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_CHECKLISTBOX && wxUSE_OWNER_DRAWN
#include "wx/checklst.h"
#ifndef WX_PRECOMP
#include "wx/msw/wrapcctl.h"
#include "wx/object.h"
#include "wx/colour.h"
#include "wx/font.h"
#include "wx/bitmap.h"
#include "wx/window.h"
#include "wx/listbox.h"
#include "wx/dcmemory.h"
#include "wx/settings.h"
#include "wx/log.h"
#endif
#include "wx/ownerdrw.h"
#include <windowsx.h>
#include "wx/renderer.h"
#include "wx/msw/private.h"
#include "wx/msw/dc.h"
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
// get item (converted to right type)
#define GetItem(n) ((wxCheckListBoxItem *)(GetItem(n)))
namespace
{
// space around check mark bitmap in pixels
static const int CHECKMARK_EXTRA_SPACE = 1;
// space between check bitmap and text label
static const int CHECKMARK_LABEL_SPACE = 2;
} // anonymous namespace
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// declaration and implementation of wxCheckListBoxItem class
// ----------------------------------------------------------------------------
class wxCheckListBoxItem : public wxOwnerDrawn
{
public:
// ctor
wxCheckListBoxItem(wxCheckListBox *parent);
// drawing functions
virtual bool OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction act, wxODStatus stat);
// simple accessors and operations
wxCheckListBox *GetParent() const
{ return m_parent; }
int GetIndex() const
{ return m_parent->GetItemIndex(const_cast<wxCheckListBoxItem*>(this)); }
wxString GetName() const
{ return m_parent->GetString(GetIndex()); }
bool IsChecked() const
{ return m_checked; }
void Check(bool bCheck)
{ m_checked = bCheck; }
void Toggle()
{ Check(!IsChecked()); }
private:
wxCheckListBox *m_parent;
bool m_checked;
wxDECLARE_NO_COPY_CLASS(wxCheckListBoxItem);
};
wxCheckListBoxItem::wxCheckListBoxItem(wxCheckListBox *parent)
{
m_parent = parent;
m_checked = false;
wxSize size = wxRendererNative::Get().GetCheckBoxSize(parent);
size.x += 2 * CHECKMARK_EXTRA_SPACE + CHECKMARK_LABEL_SPACE;
SetMarginWidth(size.GetWidth());
SetBackgroundColour(parent->GetBackgroundColour());
}
bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc,
wxODAction act, wxODStatus stat)
{
// first draw the label
if ( !wxOwnerDrawn::OnDrawItem(dc, rc, act, stat) )
return false;
// now draw the check mark part
wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
HDC hdc = GetHdcOf(*impl);
wxSize size = wxRendererNative::Get().GetCheckBoxSize(GetParent());
// first create bitmap in a memory DC
MemoryHDC hdcMem(hdc);
CompatibleBitmap hBmpCheck(hdc, size.GetWidth(), size.GetHeight());
// then draw a check mark into it
{
SelectInHDC selBmp(hdcMem, hBmpCheck);
int flags = wxCONTROL_FLAT;
if ( IsChecked() )
flags |= wxCONTROL_CHECKED;
wxDCTemp dcMem(hdcMem);
wxRendererNative::Get().DrawCheckBox(GetParent(), dcMem, wxRect(size), flags);
} // select hBmpCheck out of hdcMem
// finally draw bitmap to screen
// position of check mark bitmap
int x = rc.GetX() + CHECKMARK_EXTRA_SPACE;
int y = rc.GetY() + (rc.GetHeight() - size.GetHeight()) / 2;
UINT uState = stat & wxOwnerDrawn::wxODSelected ? wxDSB_SELECTED : wxDSB_NORMAL;
wxDrawStateBitmap(hdc, hBmpCheck, x, y, uState);
return true;
}
// ----------------------------------------------------------------------------
// implementation of wxCheckListBox class
// ----------------------------------------------------------------------------
// define event table
// ------------------
BEGIN_EVENT_TABLE(wxCheckListBox, wxListBox)
EVT_KEY_DOWN(wxCheckListBox::OnKeyDown)
EVT_LEFT_DOWN(wxCheckListBox::OnLeftClick)
END_EVENT_TABLE()
// control creation
// ----------------
// def ctor: use Create() to really create the control
wxCheckListBox::wxCheckListBox()
{
}
// ctor which creates the associated control
wxCheckListBox::wxCheckListBox(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size,
int nStrings, const wxString choices[],
long style, const wxValidator& val,
const wxString& name)
{
Create(parent, id, pos, size, nStrings, choices, style, val, name);
}
wxCheckListBox::wxCheckListBox(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size,
const wxArrayString& choices,
long style, const wxValidator& val,
const wxString& name)
{
Create(parent, id, pos, size, choices, style, val, name);
}
bool wxCheckListBox::Create(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size,
int n, const wxString choices[],
long style,
const wxValidator& validator, const wxString& name)
{
return wxListBox::Create(parent, id, pos, size, n, choices,
style | wxLB_OWNERDRAW, validator, name);
}
bool wxCheckListBox::Create(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size,
const wxArrayString& choices,
long style,
const wxValidator& validator, const wxString& name)
{
return wxListBox::Create(parent, id, pos, size, choices,
style | wxLB_OWNERDRAW, validator, name);
}
// create/retrieve item
// --------------------
// create a check list box item
wxOwnerDrawn *wxCheckListBox::CreateLboxItem(size_t WXUNUSED(n))
{
wxCheckListBoxItem *pItem = new wxCheckListBoxItem(this);
return pItem;
}
// return item size
// ----------------
bool wxCheckListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
{
if ( wxListBox::MSWOnMeasure(item) )
{
MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item;
wxSize size = wxRendererNative::Get().GetCheckBoxSize(this);
size.x += 2 * CHECKMARK_EXTRA_SPACE;
size.y += 2 * CHECKMARK_EXTRA_SPACE;
// add place for the check mark
pStruct->itemWidth += size.GetWidth();
if ( pStruct->itemHeight < static_cast<unsigned int>(size.GetHeight()) )
pStruct->itemHeight = size.GetHeight();
return true;
}
return false;
}
// check items
// -----------
bool wxCheckListBox::IsChecked(unsigned int uiIndex) const
{
wxCHECK_MSG( IsValid(uiIndex), false, wxT("bad wxCheckListBox index") );
return GetItem(uiIndex)->IsChecked();
}
void wxCheckListBox::Check(unsigned int uiIndex, bool bCheck)
{
wxCHECK_RET( IsValid(uiIndex), wxT("bad wxCheckListBox index") );
GetItem(uiIndex)->Check(bCheck);
RefreshItem(uiIndex);
}
void wxCheckListBox::Toggle(unsigned int uiIndex)
{
wxCHECK_RET( IsValid(uiIndex), wxT("bad wxCheckListBox index") );
GetItem(uiIndex)->Toggle();
RefreshItem(uiIndex);
}
// process events
// --------------
void wxCheckListBox::OnKeyDown(wxKeyEvent& event)
{
// what do we do?
enum
{
NONE,
TOGGLE,
SET,
CLEAR
} oper;
switch ( event.GetKeyCode() )
{
case WXK_SPACE:
oper = TOGGLE;
break;
case WXK_NUMPAD_ADD:
case '+':
oper = SET;
break;
case WXK_NUMPAD_SUBTRACT:
case '-':
oper = CLEAR;
break;
default:
oper = NONE;
}
if ( oper != NONE )
{
wxArrayInt selections;
int count = 0;
if ( HasMultipleSelection() )
{
count = GetSelections(selections);
}
else
{
int sel = GetSelection();
if (sel != -1)
{
count = 1;
selections.Add(sel);
}
}
for ( int i = 0; i < count; i++ )
{
int nItem = selections[i];
switch ( oper )
{
case TOGGLE:
Toggle(nItem);
break;
case SET:
case CLEAR:
Check(nItem, oper == SET);
break;
default:
wxFAIL_MSG( wxT("what should this key do?") );
}
// we should send an event as this has been done by the user and
// not by the program
SendEvent(nItem);
}
}
else // nothing to do
{
event.Skip();
}
}
void wxCheckListBox::OnLeftClick(wxMouseEvent& event)
{
// clicking on the item selects it, clicking on the checkmark toggles
int nItem = HitTest(event.GetX(), event.GetY());
if ( nItem != wxNOT_FOUND )
{
wxRect rect;
GetItemRect(nItem, rect);
// convert item rect to check mark rect
wxSize size = wxRendererNative::Get().GetCheckBoxSize(this);
rect.x += CHECKMARK_EXTRA_SPACE;
rect.y += (rect.GetHeight() - size.GetHeight()) / 2;
rect.SetSize(size);
if ( rect.Contains(event.GetX(), event.GetY()) )
{
// people expect to get "kill focus" event for the currently
// focused control before getting events from the other controls
// and, equally importantly, they may prevent the focus change from
// taking place at all (e.g. because the old control contents is
// invalid and needs to be corrected) in which case we shouldn't
// generate this event at all
SetFocus();
if ( FindFocus() == this )
{
Toggle(nItem);
SendEvent(nItem);
// scroll one item down if the item is the last one
// and isn't visible at all
int h;
GetClientSize(NULL, &h);
if ( rect.GetBottom() > h )
ScrollLines(1);
}
}
else
{
// implement default behaviour: clicking on the item selects it
event.Skip();
}
}
else
{
// implement default behaviour on click outside of client zone
event.Skip();
}
}
wxSize wxCheckListBox::DoGetBestClientSize() const
{
wxSize best = wxListBox::DoGetBestClientSize();
// add room for the checkbox
wxSize size = wxRendererNative::Get().GetCheckBoxSize(const_cast<wxCheckListBox*>(this));
size.x += 2 * CHECKMARK_EXTRA_SPACE;
size.y += 2 * CHECKMARK_EXTRA_SPACE;
best.x += size.GetWidth();
if ( best.y < size.GetHeight() )
best.y = size.GetHeight();
CacheBestSize(best);
return best;
}
#endif // wxUSE_CHECKLISTBOX