// Created: 13/07/98
// RCS-ID: $Id$
// Copyright: (c) wxWindows team
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// no window yet, no parent nor children
m_parent = (wxWindow *)NULL;
m_windowId = -1;
- m_children.DeleteContents( FALSE ); // don't auto delete node data
// no constraints on the minimal window size
m_minWidth =
m_hasBgCol =
m_hasFgCol =
m_hasFont = FALSE;
+
+ m_isBeingDeleted = FALSE;
// no style bits
m_exStyle =
m_windowStyle = 0;
- // an optimization for the event processing: checking this flag is much
- // faster than using IsKindOf(CLASSINFO(wxWindow))
- m_isWindow = TRUE;
-
#if wxUSE_CONSTRAINTS
// no constraints whatsoever
m_constraints = (wxLayoutConstraints *) NULL;
const wxValidator& validator,
const wxString& name)
{
- // m_isWindow is set to TRUE in wxWindowBase::Init() as well as many other
- // member variables - check that it has been called (will catch the case
- // when a new ctor is added which doesn't call InitWindow)
- wxASSERT_MSG( m_isWindow, wxT("Init() must have been called before!") );
-
#if wxUSE_STATBOX
// wxGTK doesn't allow to create controls with static box as the parent so
// this will result in a crash when the program is ported to wxGTK so warn
_T("wxStaticBox can't be used as a window parent!") );
#endif // wxUSE_STATBOX
+ // ids are limited to 16 bits under MSW so if you care about portability,
+ // it's not a good idea to use ids out of this range (and negative ids are
+ // reserved for wxWindows own usage)
+ wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767),
+ _T("invalid id value") );
+
// generate a new id if the user doesn't care about it
- m_windowId = id == -1 ? NewControlId() : id;
+ m_windowId = id == wxID_ANY ? NewControlId() : id;
SetName(name);
SetWindowStyleFlag(style);
// Just in case we've loaded a top-level window via LoadNativeDialog but
// we weren't a dialog class
- wxTopLevelWindows.DeleteObject(this);
+ wxTopLevelWindows.DeleteObject((wxWindow*)this);
wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
bool wxWindowBase::DestroyChildren()
{
- wxWindowList::Node *node;
+ wxWindowList::compatibility_iterator node;
for ( ;; )
{
// we iterate until the list becomes empty
int maxX = 0,
maxY = 0;
- for ( wxWindowList::Node *node = GetChildren().GetFirst();
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{
int maxX = 0,
maxY = 0;
- for ( wxWindowList::Node *node = GetChildren().GetFirst();
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{
// setting min width greater than max width leads to infinite loops under
// X11 and generally doesn't make any sense, so don't allow it
wxCHECK_RET( (minW == -1 || maxW == -1 || minW <= maxW) &&
- (minH == -1 || maxH == -1 || minH < maxH),
+ (minH == -1 || maxH == -1 || minH <= maxH),
_T("min width/height must be less than max width/height!") );
m_minWidth = minW;
// this should never happen and it will lead to a crash later if it does
// because RemoveChild() will remove only one node from the children list
// and the other(s) one(s) will be left with dangling pointers in them
- wxASSERT_MSG( !GetChildren().Find(child), _T("AddChild() called twice") );
+ wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), _T("AddChild() called twice") );
- GetChildren().Append(child);
+ GetChildren().Append((wxWindow*)child);
child->SetParent(this);
}
{
wxCHECK_RET( child, wxT("can't remove a NULL child") );
- GetChildren().DeleteObject(child);
- child->SetParent((wxWindow *)NULL);
+ GetChildren().DeleteObject((wxWindow *)child);
+ child->SetParent(NULL);
}
bool wxWindowBase::Reparent(wxWindowBase *newParent)
}
else
{
- wxTopLevelWindows.DeleteObject(this);
+ wxTopLevelWindows.DeleteObject((wxWindow *)this);
}
// add it to the new one
}
else
{
- wxTopLevelWindows.Append(this);
+ wxTopLevelWindows.Append((wxWindow *)this);
}
return TRUE;
return (wxWindow *)this;
wxWindowBase *res = (wxWindow *)NULL;
- wxWindowList::Node *node;
+ wxWindowList::compatibility_iterator node;
for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
{
wxWindowBase *child = node->GetData();
return (wxWindow *)this;
wxWindowBase *res = (wxWindow *)NULL;
- wxWindowList::Node *node;
+ wxWindowList::compatibility_iterator node;
for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
{
wxWindow *child = node->GetData();
return (wxWindow *)parent;
// It wasn't, so check all its children
- for ( wxWindowList::Node * node = parent->GetChildren().GetFirst();
+ for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
node;
node = node->GetNext() )
{
}
// start at very top of wx's windows
- for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
+ for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
node;
node = node->GetNext() )
{
// Disable all other windows
if ( IsTopLevel() )
{
- wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
+ wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
while (node)
{
wxWindow *win = node->GetData();
#if wxUSE_VALIDATORS
bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
- wxWindowList::Node *node;
+ wxWindowList::compatibility_iterator node;
for ( node = m_children.GetFirst(); node; node = node->GetNext() )
{
wxWindowBase *child = node->GetData();
#if wxUSE_VALIDATORS
bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
- wxWindowList::Node *node;
+ wxWindowList::compatibility_iterator node;
for ( node = m_children.GetFirst(); node; node = node->GetNext() )
{
wxWindowBase *child = node->GetData();
#if wxUSE_VALIDATORS
bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
- wxWindowList::Node *node;
+ wxWindowList::compatibility_iterator node;
for ( node = m_children.GetFirst(); node; node = node->GetNext() )
{
wxWindow *child = node->GetData();
{
if ( !m_constraintsInvolvedIn )
m_constraintsInvolvedIn = new wxWindowList;
- if ( !m_constraintsInvolvedIn->Find(otherWin) )
- m_constraintsInvolvedIn->Append(otherWin);
+ if ( !m_constraintsInvolvedIn->Find((wxWindow *)otherWin) )
+ m_constraintsInvolvedIn->Append((wxWindow *)otherWin);
}
// REMOVE back-pointer to other windows we're involved with.
void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
{
if ( m_constraintsInvolvedIn )
- m_constraintsInvolvedIn->DeleteObject(otherWin);
+ m_constraintsInvolvedIn->DeleteObject((wxWindow *)otherWin);
}
// Reset any constraints that mention this window
{
if ( m_constraintsInvolvedIn )
{
- wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
+ wxWindowList::compatibility_iterator node = m_constraintsInvolvedIn->GetFirst();
while (node)
{
wxWindow *win = node->GetData();
constr->centreY.ResetIfWin(this);
}
- wxWindowList::Node *next = node->GetNext();
- delete node;
+ wxWindowList::compatibility_iterator next = node->GetNext();
+ m_constraintsInvolvedIn->Erase(node);
node = next;
}
int noChanges = 0;
// loop over all children setting their constraints
- for ( wxWindowList::Node *node = GetChildren().GetFirst();
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{
constr->centreY.SetDone(FALSE);
}
- wxWindowList::Node *node = GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
while (node)
{
wxWindow *win = node->GetData();
if ( recurse )
{
- wxWindowList::Node *node = GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
while (node)
{
wxWindow *win = node->GetData();
// do Update UI processing for child controls
// ----------------------------------------------------------------------------
-// TODO: should this be implemented for the child window rather
-// than the parent? Then you can override it e.g. for wxCheckBox
-// to do the Right Thing rather than having to assume a fixed number
-// of control classes.
-void wxWindowBase::UpdateWindowUI()
+void wxWindowBase::UpdateWindowUI(long flags)
{
-#if wxUSE_CONTROLS
wxUpdateUIEvent event(GetId());
event.m_eventObject = this;
if ( GetEventHandler()->ProcessEvent(event) )
{
- if ( event.GetSetEnabled() )
- Enable(event.GetEnabled());
+ DoUpdateWindowUI(event);
+ }
- if ( event.GetSetText() )
+ if (flags & wxUPDATE_UI_RECURSE)
+ {
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ while (node)
{
- wxControl *control = wxDynamicCastThis(wxControl);
- if ( control )
- {
-#if wxUSE_TEXTCTRL
- wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl);
- if ( text )
- {
- if ( event.GetText() != text->GetValue() )
- text->SetValue(event.GetText());
- }
- else
-#endif // wxUSE_TEXTCTRL
- {
- if ( event.GetText() != control->GetLabel() )
- control->SetLabel(event.GetText());
- }
- }
+ wxWindow* child = (wxWindow*) node->GetData();
+ child->UpdateWindowUI(flags);
+ node = node->GetNext();
}
+ }
+}
+// do the window-specific processing after processing the update event
+// TODO: take specific knowledge out of this function and
+// put in each control's base class. Unfortunately we don't
+// yet have base implementation files for wxCheckBox and wxRadioButton.
+void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
+{
+ if ( event.GetSetEnabled() )
+ Enable(event.GetEnabled());
+
+#if wxUSE_CONTROLS
+ if ( event.GetSetText() )
+ {
+ wxControl *control = wxDynamicCastThis(wxControl);
+ if ( control )
+ {
+ if ( event.GetText() != control->GetLabel() )
+ control->SetLabel(event.GetText());
+ }
#if wxUSE_CHECKBOX
wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
if ( checkbox )
radiobtn->SetValue(event.GetChecked());
}
#endif // wxUSE_RADIOBTN
+ }
+#endif
+}
+
+#if 0
+// call internal idle recursively
+// may be obsolete (wait until OnIdle scheme stabilises)
+void wxWindowBase::ProcessInternalIdle()
+{
+ OnInternalIdle();
+
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ while (node)
+ {
+ wxWindow *child = node->GetData();
+ child->ProcessInternalIdle();
+ node = node->GetNext();
}
-#endif // wxUSE_CONTROLS
}
+#endif
// ----------------------------------------------------------------------------
// dialog units translations
// propagate the colour change event to the subwindows
void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
{
- wxWindowList::Node *node = GetChildren().GetFirst();
+ wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
while ( node )
{
// Only propagate to non-top-level windows
}
}
-// the default action is to populate dialog with data when it's created
+// the default action is to populate dialog with data when it's created,
+// and nudge the UI into displaying itself correctly in case
+// we've turned the wxUpdateUIEvents frequency down low.
void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
{
TransferDataToWindow();
+
+ // Update the UI at this point
+ UpdateWindowUI(wxUPDATE_UI_RECURSE);
}
// process Ctrl-Alt-mclick
#endif
+#if !wxUSE_STL
// ----------------------------------------------------------------------------
// list classes implementation
// ----------------------------------------------------------------------------
{
delete (wxWindow *)GetData();
}
+#endif
// ----------------------------------------------------------------------------
// borders
// ----------------------------------------------------------------------------
-wxBorder wxWindowBase::GetBorder() const
+wxBorder wxWindowBase::GetBorder(long flags) const
{
- wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK);
+ wxBorder border = (wxBorder)(flags & wxBORDER_MASK);
if ( border == wxBORDER_DEFAULT )
{
border = GetDefaultBorder();
GetCapture());
}
+#if wxUSE_HOTKEY
+
+bool
+wxWindowBase::RegisterHotKey(int WXUNUSED(hotkeyId),
+ int WXUNUSED(modifiers),
+ int WXUNUSED(keycode))
+{
+ // not implemented
+ return false;
+}
+
+bool wxWindowBase::UnregisterHotKey(int WXUNUSED(hotkeyId))
+{
+ // not implemented
+ return false;
+}
+
+#endif // wxUSE_HOTKEY
void wxWindowBase::SendDestroyEvent()
{
GetEventHandler()->ProcessEvent(event);
}
+// ----------------------------------------------------------------------------
+// event processing
+// ----------------------------------------------------------------------------
+
+#if wxUSE_VALIDATORS
+
+bool wxWindowBase::TryValidator(wxEvent& event)
+{
+ // Can only use the validator of the window which
+ // is receiving the event
+ if ( event.GetEventObject() == this )
+ {
+ wxValidator *validator = GetValidator();
+ if ( validator && validator->ProcessEvent(event) )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif // wxUSE_VALIDATORS
+
+bool wxWindowBase::TryParent(wxEvent& event)
+{
+ // Carry on up the parent-child hierarchy, but only if event is a command
+ // event: it wouldn't make sense for a parent to receive a child's size
+ // event, for example
+ if ( event.IsCommandEvent() )
+ {
+ // honour the requests to stop propagation at this window: this is
+ // used by the dialogs, for example, to prevent processing the events
+ // from the dialog controls in the parent frame which rarely, if ever,
+ // makes sense
+ if ( !(GetExtraStyle() & wxWS_EX_BLOCK_EVENTS) )
+ {
+ wxWindow *parent = GetParent();
+ if ( parent && !parent->IsBeingDeleted() )
+ return parent->GetEventHandler()->ProcessEvent(event);
+ }
+ }
+
+ return wxEvtHandler::TryParent(event);
+}
+
// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------
case wxNAVDIR_DOWN:
case wxNAVDIR_NEXT:
{
- wxWindowList::Node *node = NULL;
+ wxWindowList::compatibility_iterator node = NULL;
if (fromId == 0)
{
// Can't navigate to sibling of this window
else
{
if (fromId <= (int) GetWindow()->GetChildren().GetCount())
- node = (wxWindowList::Node*) GetWindow()->GetChildren().Nth(fromId-1);
+ node = GetWindow()->GetChildren().Nth(fromId-1);
}
if (node && node->GetNext())
case wxNAVDIR_UP:
case wxNAVDIR_PREVIOUS:
{
- wxWindowList::Node *node = NULL;
+ wxWindowList::compatibility_iterator node = NULL;
if (fromId == 0)
{
// Can't navigate to sibling of this window
else
{
if (fromId <= (int) GetWindow()->GetChildren().GetCount())
- node = (wxWindowList::Node*) GetWindow()->GetChildren().Nth(fromId-1);
+ node = GetWindow()->GetChildren().Nth(fromId-1);
}
if (node && node->GetPrevious())