diff --git a/include/wx/osx/cocoa/dataview.h b/include/wx/osx/cocoa/dataview.h index c464cbd50e..871833e83a 100644 --- a/include/wx/osx/cocoa/dataview.h +++ b/include/wx/osx/cocoa/dataview.h @@ -557,6 +557,9 @@ private: wxCocoaOutlineDataSource* m_DataSource; wxCocoaOutlineView* m_OutlineView; + + // Width of expander in pixels, computed on demand. + int m_expanderWidth; }; #endif // _WX_DATAVIEWCTRL_COCOOA_H_ diff --git a/include/wx/osx/dataview.h b/include/wx/osx/dataview.h index 28e4d557c2..15458caca6 100644 --- a/include/wx/osx/dataview.h +++ b/include/wx/osx/dataview.h @@ -306,7 +306,7 @@ private: wxDataViewColumnPtrArrayType m_ColumnPtrs; // all column pointers are stored in an array - wxDataViewModelNotifier* m_ModelNotifier; // stores the model notifier for the control (does not own the notifier) + class wxOSXDataViewModelNotifier* m_ModelNotifier; // stores the model notifier for the control (does not own the notifier) // wxWidget internal stuff: wxDECLARE_DYNAMIC_CLASS(wxDataViewCtrl); diff --git a/include/wx/osx/listbox.h b/include/wx/osx/listbox.h index 5e8949e700..ed86f5c7d8 100644 --- a/include/wx/osx/listbox.h +++ b/include/wx/osx/listbox.h @@ -170,6 +170,8 @@ protected: wxArrayPtrVoid m_itemsClientData; private: + // Mostly the same as DoSetSelection() but doesn't call EnsureVisible(). + void DoSetSelectionWithoutEnsureVisible(int n, bool select); wxDECLARE_DYNAMIC_CLASS(wxListBox); wxDECLARE_EVENT_TABLE(); diff --git a/src/osx/carbon/app.cpp b/src/osx/carbon/app.cpp index 4d4f3a89ce..1b6cefa687 100644 --- a/src/osx/carbon/app.cpp +++ b/src/osx/carbon/app.cpp @@ -169,16 +169,16 @@ void wxApp::MacReopenApp() while (node) { wxTopLevelWindow* win = (wxTopLevelWindow*) node->GetData(); - if ( win->IsShown() ) - { - // we do have a visible, non-iconized toplevelwindow -> do nothing - return; - } - else if ( win->IsIconized() ) + if ( win->IsIconized() ) { if ( firstIconized == NULL ) firstIconized = win; } + else if ( win->IsShown() ) + { + // we do have a visible, non-iconized toplevelwindow -> do nothing + return; + } node = node->GetNext(); } diff --git a/src/osx/carbon/renderer.cpp b/src/osx/carbon/renderer.cpp index 8d3fd41b54..71e9535c53 100644 --- a/src/osx/carbon/renderer.cpp +++ b/src/osx/carbon/renderer.cpp @@ -348,11 +348,14 @@ void wxRendererMac::DrawSplitterSash( wxWindow *win, height = wxRendererNative::Get().GetSplitterParams(win).widthSash; + // Do not draw over border drawn by wxRendererGeneric::DrawSplitterBorder() + const wxCoord borderAdjust = win->HasFlag(wxSP_3DBORDER) ? 2 : 0; + HIRect splitterRect; if (orient == wxVERTICAL) - splitterRect = CGRectMake( position, 0, height, size.y ); + splitterRect = CGRectMake( position, borderAdjust, height, size.y - 2*borderAdjust ); else - splitterRect = CGRectMake( 0, position, size.x, height ); + splitterRect = CGRectMake( borderAdjust, position, size.x - 2*borderAdjust, height ); // under compositing we should only draw when called by the OS, otherwise just issue a redraw command // strange redraw errors occur if we don't do this diff --git a/src/osx/cocoa/combobox.mm b/src/osx/cocoa/combobox.mm index 7fc69b1276..5b8ffd938d 100644 --- a/src/osx/cocoa/combobox.mm +++ b/src/osx/cocoa/combobox.mm @@ -139,23 +139,30 @@ - (void)comboBoxSelectionDidChange:(NSNotification *)notification { wxUnusedVar(notification); - wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + wxNSComboBoxControl* const + impl = (wxNSComboBoxControl* ) wxWidgetImpl::FindFromWXWidget( self ); if ( impl && impl->ShouldSendEvents()) { wxComboBox* wxpeer = static_cast(impl->GetWXPeer()); if ( wxpeer ) { const int sel = wxpeer->GetSelection(); + const wxString& val = wxpeer->GetString(sel); + + // We need to manually set the new value because at this time it + // still contains the old value, but we want GetValue() to return + // the new one if it's called from an event handler invoked below. + impl->SetStringValue(val); wxCommandEvent event(wxEVT_COMBOBOX, wxpeer->GetId()); event.SetEventObject( wxpeer ); event.SetInt( sel ); - event.SetString( wxpeer->GetString(sel) ); - // For some reason, wxComboBox::GetValue will not return the newly selected item - // while we're inside this callback, so use AddPendingEvent to make sure - // GetValue() returns the right value. - - wxpeer->GetEventHandler()->AddPendingEvent( event ); + event.SetString( val ); + wxpeer->HandleWindowEvent( event ); + wxCommandEvent eventText(wxEVT_TEXT, wxpeer->GetId()); + eventText.SetEventObject( wxpeer ); + eventText.SetString( val ); + wxpeer->HandleWindowEvent( eventText ); } } } diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 40c4fd2c59..46af4690db 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -2045,7 +2045,8 @@ wxCocoaDataViewControl::wxCocoaDataViewControl(wxWindow* peer, [[NSScrollView alloc] initWithFrame:wxOSXGetFrameForControl(peer,pos,size)] ), m_DataSource(NULL), - m_OutlineView([[wxCocoaOutlineView alloc] init]) + m_OutlineView([[wxCocoaOutlineView alloc] init]), + m_expanderWidth(0) { // initialize scrollview (the outline view is part of a scrollview): NSScrollView* scrollview = (NSScrollView*) GetWXWidget(); @@ -2175,7 +2176,9 @@ void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos) : m_width(0), m_view(view), m_column(columnIndex), - m_indent(0) + m_indent(0), + m_expander(0), + m_tableColumn(column) { // account for indentation in the column with expander if ( column == [m_view outlineTableColumn] ) @@ -2193,18 +2196,27 @@ void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos) unsigned cellWidth = [cell cellSize].width + 1/*round the float up*/; if ( m_indent ) - cellWidth += m_indent * ([m_view levelForRow:row] + 1); + cellWidth += m_indent * [m_view levelForRow:row]; + + if ( m_expander == 0 && m_tableColumn == [m_view outlineTableColumn] ) + { + NSRect rc = [m_view frameOfOutlineCellAtRow:row]; + m_expander = ceil(rc.origin.x + rc.size.width); + } m_width = wxMax(m_width, cellWidth); } int GetMaxWidth() const { return m_width; } + int GetExpanderWidth() const { return m_expander; } private: int m_width; wxCocoaOutlineView *m_view; unsigned m_column; int m_indent; + int m_expander; + NSTableColumn *m_tableColumn; }; MaxWidthCalculator calculator(m_OutlineView, column, pos); @@ -2275,7 +2287,12 @@ void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos) count); } - [column setWidth:calculator.GetMaxWidth()]; + // there might not necessarily be an expander in the rows we've examined above so let's + // globally store the expander width for re-use because it should always be the same + if ( m_expanderWidth == 0 ) + m_expanderWidth = calculator.GetExpanderWidth(); + + [column setWidth:calculator.GetMaxWidth() + m_expanderWidth]; } // diff --git a/src/osx/cocoa/listbox.mm b/src/osx/cocoa/listbox.mm index 766686a81f..216142b026 100644 --- a/src/osx/cocoa/listbox.mm +++ b/src/osx/cocoa/listbox.mm @@ -149,9 +149,15 @@ public : protected : + void AdaptColumnWidth ( int w ); + wxNSTableView* m_tableView ; wxNSTableDataSource* m_dataSource; + + NSMutableArray* m_widths; + int m_maxWidth; + bool m_autoSize; } ; // @@ -333,10 +339,14 @@ wxListWidgetCocoaImpl::wxListWidgetCocoaImpl( wxWindowMac* peer, NSScrollView* v wxWidgetCocoaImpl( peer, view ), m_tableView(tableview), m_dataSource(data) { InstallEventHandler( tableview ); + m_widths = [[NSMutableArray alloc] init]; + m_maxWidth = 0; + m_autoSize = false; } wxListWidgetCocoaImpl::~wxListWidgetCocoaImpl() { + [m_widths release]; [m_dataSource release]; } @@ -371,11 +381,7 @@ wxListWidgetColumn* wxListWidgetCocoaImpl::InsertTextColumn( unsigned pos, const } else { - [col1 setMaxWidth:1000]; - [col1 setMinWidth:10]; - // temporary hack, because I cannot get the automatic column resizing - // to work properly - [col1 setWidth:1000]; + m_autoSize = true; } [col1 setResizingMask: NSTableColumnAutoresizingMask]; @@ -465,24 +471,65 @@ wxListWidgetColumn* wxListWidgetCocoaImpl::InsertCheckColumn( unsigned pos , con return wxcol; } +void wxListWidgetCocoaImpl::AdaptColumnWidth ( int w ) +{ + NSTableColumn *col = [[m_tableView tableColumns] objectAtIndex:0]; + [col setWidth:w]; + m_maxWidth = w; +} // // inserting / removing lines // -void wxListWidgetCocoaImpl::ListInsert( unsigned int WXUNUSED(n) ) +void wxListWidgetCocoaImpl::ListInsert( unsigned int n ) { [m_tableView reloadData]; + + if ( m_autoSize ) + { + NSCell *cell = [m_tableView preparedCellAtColumn:0 row:n]; + NSSize size = [cell cellSize]; + int width = (int) ceil(size.width); + + [m_widths insertObject:[NSNumber numberWithInteger:width] atIndex:n]; + + if ( width > m_maxWidth ) + AdaptColumnWidth( width ); + } } -void wxListWidgetCocoaImpl::ListDelete( unsigned int WXUNUSED(n) ) +void wxListWidgetCocoaImpl::ListDelete( unsigned int n ) { [m_tableView reloadData]; + + if ( m_autoSize ) + { + [m_widths removeObjectAtIndex:n]; + + int maxWidth = 0; + for ( NSNumber *number in m_widths ) + { + int n = [number intValue]; + + if ( n > maxWidth ) + maxWidth = n; + } + + if ( maxWidth < m_maxWidth ) + AdaptColumnWidth( maxWidth ); + } } void wxListWidgetCocoaImpl::ListClear() { [m_tableView reloadData]; + + if ( m_autoSize ) + { + [m_widths removeAllObjects]; + AdaptColumnWidth( 100 ); + } } // selecting diff --git a/src/osx/cocoa/settings.mm b/src/osx/cocoa/settings.mm index 99fd931774..472d40b424 100644 --- a/src/osx/cocoa/settings.mm +++ b/src/osx/cocoa/settings.mm @@ -128,6 +128,7 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index) case wxSYS_COLOUR_MENUTEXT: case wxSYS_COLOUR_WINDOWTEXT: case wxSYS_COLOUR_CAPTIONTEXT: + case wxSYS_COLOUR_INACTIVECAPTIONTEXT: case wxSYS_COLOUR_INFOTEXT: case wxSYS_COLOUR_LISTBOXTEXT: sysColor = [NSColor controlTextColor]; @@ -138,7 +139,6 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index) case wxSYS_COLOUR_BTNHIGHLIGHT: sysColor = [NSColor controlHighlightColor]; break; - case wxSYS_COLOUR_INACTIVECAPTIONTEXT: case wxSYS_COLOUR_GRAYTEXT: sysColor = [NSColor disabledControlTextColor]; break; diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index aad774429f..d915d62ecd 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -1470,6 +1470,26 @@ void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd) return; } + // The Infinity IN-USB-2 V15 foot pedal on OS 11 produces spurious mouse + // button events with button number = 10. + // We cannot do anything useful with button numbers > 2, so throw them away. + switch ( [event type] ) + { + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + if ( [event buttonNumber] > 2 ) + return; + break; + + default: + // Just to avoid -Wswitch. + break; + } + if ( !DoHandleMouseEvent(event) ) { // for plain NSView mouse events would propagate to parents otherwise @@ -2420,11 +2440,12 @@ void wxWidgetCocoaImpl::controlTextDidChange() if ( wxpeer ) { // since native rtti doesn't have to be enabled and wx' rtti is not aware of the mixin wxTextEntry, workaround is needed - wxTextCtrl *tc = wxDynamicCast( wxpeer , wxTextCtrl ); - wxComboBox *cb = wxDynamicCast( wxpeer , wxComboBox ); - if ( tc ) + if ( wxTextCtrl *tc = wxDynamicCast( wxpeer , wxTextCtrl ) ) + { + tc->MarkDirty(); tc->SendTextUpdatedEventIfAllowed(); - else if ( cb ) + } + else if ( wxComboBox *cb = wxDynamicCast( wxpeer , wxComboBox ) ) cb->SendTextUpdatedEventIfAllowed(); else { diff --git a/src/osx/dataview_osx.cpp b/src/osx/dataview_osx.cpp index 9812036eef..60edfcbfe2 100644 --- a/src/osx/dataview_osx.cpp +++ b/src/osx/dataview_osx.cpp @@ -73,14 +73,15 @@ public: virtual bool Cleared() wxOVERRIDE; virtual void Resort() wxOVERRIDE; + // adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data + void AdjustAutosizedColumns(); + protected: // if the dataview control can have a variable row height this method sets the dataview's control row height of // the passed item to the maximum value occupied by the item in all columns void AdjustRowHeight(wxDataViewItem const& item); // ... and the same method for a couple of items: void AdjustRowHeights(wxDataViewItemArray const& items); - // adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data - void AdjustAutosizedColumns(); private: wxDataViewCtrl* m_DataViewCtrlPtr; @@ -505,6 +506,9 @@ int wxDataViewCtrl::GetColumnPosition(wxDataViewColumn const* columnPtr) const void wxDataViewCtrl::Collapse(wxDataViewItem const& item) { GetDataViewPeer()->Collapse(item); + + if ( m_ModelNotifier ) + m_ModelNotifier->AdjustAutosizedColumns(); } void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) @@ -518,7 +522,10 @@ void wxDataViewCtrl::EnsureVisible(wxDataViewItem const& item, wxDataViewColumn void wxDataViewCtrl::DoExpand(wxDataViewItem const& item, bool expandChildren) { - return GetDataViewPeer()->DoExpand(item, expandChildren); + GetDataViewPeer()->DoExpand(item, expandChildren); + + if ( m_ModelNotifier ) + m_ModelNotifier->AdjustAutosizedColumns(); } bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const diff --git a/src/osx/listbox_osx.cpp b/src/osx/listbox_osx.cpp index e97d1b6c88..961141df13 100644 --- a/src/osx/listbox_osx.cpp +++ b/src/osx/listbox_osx.cpp @@ -191,6 +191,14 @@ void wxListBox::DoSetSelection(int n, bool select) wxCHECK_RET( n == wxNOT_FOUND || IsValid(n), wxT("invalid index in wxListBox::SetSelection") ); + DoSetSelectionWithoutEnsureVisible(n, select); + + if (select) + EnsureVisible(n); +} + +void wxListBox::DoSetSelectionWithoutEnsureVisible(int n, bool select) +{ m_blockEvents = true; if ( n == wxNOT_FOUND ) @@ -201,9 +209,6 @@ void wxListBox::DoSetSelection(int n, bool select) m_blockEvents = false; UpdateOldSelections(); - - if (select) - EnsureVisible(n); } bool wxListBox::IsSelected(int n) const @@ -349,6 +354,23 @@ int wxListBox::DoInsertItems(const wxArrayStringsAdapter& items, { int idx = wxNOT_FOUND; unsigned int startpos = pos; + wxArrayInt selections; + + if ( !IsSorted() ) + { + if ( HasMultipleSelection() ) + { + GetSelections(selections); + } + else + { + int sel = GetSelection(); + if ( sel != wxNOT_FOUND ) + { + selections.Add(sel); + } + } + } const unsigned int numItems = items.GetCount(); for ( unsigned int i = 0; i < numItems; ++i ) @@ -367,13 +389,29 @@ int wxListBox::DoInsertItems(const wxArrayStringsAdapter& items, GetListPeer()->UpdateLineToEnd(startpos); - // Inserting the items may scroll the listbox down to show the last - // selected one but we don't want to do it as it could result in e.g. the - // first items of a listbox be hidden immediately after its creation so - // show the first selected item instead. Ideal would probably be to - // preserve the old selection unchanged, in fact, but I don't know how to - // get the first visible item so for now do at least this. - SetFirstItem(startpos); + const size_t numSelections = selections.size(); + for ( size_t i = 0; i < numSelections; ++i ) + { + if ( startpos <= selections[i] ) + { + if ( HasMultipleSelection() ) + { + size_t j; + + // Do not deselect item if it is to be selected below + for ( j = 0; j < numSelections; ++j ) + { + if ( selections[i] == selections[j] + numItems ) + break; + } + + if ( j == numSelections ) + Deselect(selections[i]); + } + + DoSetSelectionWithoutEnsureVisible(selections[i] + numItems, true); + } + } InvalidateBestSize();