Permalink
Browse files

CurrentTabsPopup improvements

* 0/Ctrl-0 now act as cursor-down
* Shift-0/Shift-Ctrl-0 now act as cursor-up
* Clicking outside of the popup will dismiss it
* When the list is long enough to scroll, wrap-around handling will make
  sure the new selection is still visible
  • Loading branch information...
1 parent 7fa8d80 commit 7b335f036f1c6fd46e50115286181899b2579f53 @adamv adamv committed Nov 4, 2009
Showing with 168 additions and 71 deletions.
  1. +154 −47 src/CurrentTabsPopup.cpp
  2. +8 −20 src/CurrentTabsPopup.h
  3. +4 −1 src/wxListCtrlEx.cpp
  4. +2 −3 src/wxListCtrlEx.h
View
201 src/CurrentTabsPopup.cpp
@@ -1,85 +1,121 @@
#include "CurrentTabsPopup.h"
#include "wxListCtrlEx.h"
-BEGIN_EVENT_TABLE(CurrentTabsPopup::ListEventHandler, wxEvtHandler)
- EVT_CHAR(CurrentTabsPopup::ListEventHandler::OnChar)
- EVT_LIST_ITEM_ACTIVATED(wxID_ANY, CurrentTabsPopup::ListEventHandler::OnItemActivated)
+enum CurrentTabsPopup_Columns {
+ col_Number = 0,
+ col_Filename,
+ col_Path,
+ col_ColumnCount
+};
+
+enum CurrentTabsPopup_IDs {
+ ID_TAB_LIST = 100,
+};
+
+class ListEventHandler : public wxEvtHandler {
+public:
+ ListEventHandler(CurrentTabsPopup* parent);
+
+private:
+ DECLARE_EVENT_TABLE();
+ void OnChar(wxKeyEvent& event);
+ void OnKeyDown(wxKeyEvent& event);
+
+ CurrentTabsPopup* m_parent;
+};
+
+
+BEGIN_EVENT_TABLE(ListEventHandler, wxEvtHandler)
+ EVT_CHAR(ListEventHandler::OnChar)
+ EVT_KEY_DOWN(ListEventHandler::OnKeyDown)
END_EVENT_TABLE()
-void CurrentTabsPopup::ListEventHandler::OnChar(wxKeyEvent& event) {
- switch ( event.GetKeyCode() )
- {
+void ListEventHandler::OnKeyDown(wxKeyEvent& event) {
+ const int key_code = event.GetKeyCode();
+ const int modifiers = event.GetModifiers();
+
+ if (! (modifiers == wxMOD_CONTROL || modifiers == (wxMOD_CONTROL|wxMOD_SHIFT)) ) {
+ event.Skip();
+ return;
+ }
+
+ if (key_code == 48) { // Zero key
+ if (modifiers & wxMOD_SHIFT) // go up
+ m_parent->WrapToPrevItem(true);
+ else // go down
+ m_parent->WrapToNextItem(true);
+
+ return;
+ }
+
+ event.Skip();
+}
+
+void ListEventHandler::OnChar(wxKeyEvent& event) {
+ int key_code = event.GetKeyCode();
+ switch ( key_code ) {
case WXK_ESCAPE:
// Cancel tab selection.
m_parent->EndModal(wxID_CANCEL);
return;
case WXK_UP: {
- // Wrap to bottom of the list if needed.
- int row = m_parent->m_list->GetSelectedRow();
- if (row == 0) {
- int max = m_parent->m_list->GetItemCount();
- m_parent->m_list->SetSelectedRow(max-1);
+ if (m_parent->WrapToPrevItem())
return;
- }
- break;
+
+ break; // event.Skip() will handle normal up arrow handling
}
case WXK_DOWN: {
- // Wrap to top of the list if needed.
- int row = m_parent->m_list->GetSelectedRow();
- int max = m_parent->m_list->GetItemCount();
- if (row == max -1) {
- m_parent->m_list->SetSelectedRow(0);
+ if (m_parent->WrapToNextItem())
return;
- }
- break;
+
+ break; // event.Skip() will handle normal down arrow handling
}
default:
const wxChar c = event.GetUnicodeKey();
// If a number 1-9 was pressed, and we have that many rows,
// then choose that (-1) as the selected row index.
if ((wxT('1') <= c) && ( c <= wxT('9'))) {
- int max = m_parent->m_list->GetItemCount();
-
int choice = c-wxT('1');
- if (choice < max) {
- m_parent->m_selectedTabIndex = choice;
- m_parent->EndModal(wxID_OK);
- }
+ m_parent->SelectRow(choice);
+ return;
+ }
+ else if (wxT('0') == c) { // Zero moves selection down
+ m_parent->WrapToNextItem(true);
+ return;
+ }
+ else if (wxT(')') == c) { // Shift-Zero moves selection up
+ m_parent->WrapToPrevItem(true);
return;
}
+ break;
}
event.Skip();
}
-void CurrentTabsPopup::ListEventHandler::OnItemActivated(wxListEvent& WXUNUSED(event)) {
- long itemIndex = m_parent->m_list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
- if (itemIndex == -1) {
- m_parent->EndModal(wxID_CANCEL);
- }
- else {
- m_parent->m_selectedTabIndex = itemIndex;
- m_parent->EndModal(wxID_OK);
- }
-}
-
-CurrentTabsPopup::ListEventHandler::ListEventHandler( CurrentTabsPopup* parent ):
+ListEventHandler::ListEventHandler( CurrentTabsPopup* parent ):
m_parent(parent) {}
BEGIN_EVENT_TABLE(CurrentTabsPopup, wxDialog)
EVT_SHOW(CurrentTabsPopup::OnShow)
+ EVT_LEFT_DOWN(CurrentTabsPopup::OnMouseLeftDown)
+ EVT_MOUSE_CAPTURE_LOST(CurrentTabsPopup::OnMouseCaptureLost)
END_EVENT_TABLE()
+void CurrentTabsPopup::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) {}
+
void CurrentTabsPopup::OnShow(wxShowEvent& WXUNUSED(event)) {
m_list->SetFocus();
m_list->SetSelectedRow(0);
- m_list->SetColumnWidth(0, wxLIST_AUTOSIZE); // '#'
- m_list->SetColumnWidth(1, wxLIST_AUTOSIZE); // 'Filename'
- m_list->SetColumnWidth(2, wxLIST_AUTOSIZE_USEHEADER); // 'Path'
+ m_list->SetColumnWidth(col_Number, wxLIST_AUTOSIZE);
+ m_list->SetColumnWidth(col_Filename, wxLIST_AUTOSIZE);
+ m_list->SetColumnWidth(col_Path, wxLIST_AUTOSIZE_USEHEADER);
+
+ this->CaptureMouse();
}
CurrentTabsPopup::CurrentTabsPopup(wxWindow* parent, const std::vector<OpenTabInfo*>& tabInfo):
@@ -88,10 +124,10 @@ CurrentTabsPopup::CurrentTabsPopup(wxWindow* parent, const std::vector<OpenTabIn
{
wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
- m_list = new wxListCtrlEx(this, wxID_ANY, wxPoint(0,0), wxSize(500,300), wxLC_REPORT|wxLC_SINGLE_SEL);
- m_list->InsertColumn(CurrentTabsPopup::Number, wxT("#"));
- m_list->InsertColumn(CurrentTabsPopup::Filename, wxT("Filename"));
- m_list->InsertColumn(CurrentTabsPopup::Path, wxT("Path"));
+ m_list = new wxListCtrlEx(this, ID_TAB_LIST, wxPoint(0,0), wxSize(500,300), wxLC_REPORT|wxLC_SINGLE_SEL);
+ m_list->InsertColumn(col_Number, wxT("#"));
+ m_list->InsertColumn(col_Filename, wxT("Filename"));
+ m_list->InsertColumn(col_Path, wxT("Path"));
int index = 0;
for (std::vector<OpenTabInfo*>::const_iterator p = tabInfo.begin(); p != tabInfo.end(); ++p) {
@@ -100,8 +136,8 @@ CurrentTabsPopup::CurrentTabsPopup(wxWindow* parent, const std::vector<OpenTabIn
else
m_list->InsertItem(index, wxT(""));
- m_list->SetItem(index, CurrentTabsPopup::Filename, (*p)->filename);
- m_list->SetItem(index, CurrentTabsPopup::Path, (*p)->path);
+ m_list->SetItem(index, col_Filename, (*p)->filename);
+ m_list->SetItem(index, col_Path, (*p)->path);
index++;
}
@@ -113,9 +149,80 @@ CurrentTabsPopup::CurrentTabsPopup(wxWindow* parent, const std::vector<OpenTabIn
}
CurrentTabsPopup::~CurrentTabsPopup() {
+ if (this->HasCapture())
+ this->ReleaseMouse();
+
m_list->PopEventHandler(true);
}
int CurrentTabsPopup::GetSelectedTabIndex() const {
return m_selectedTabIndex;
}
+
+bool CurrentTabsPopup::WrapToNextItem(bool full_service) {
+ // Wrap to top of the list if needed.
+ int row = m_list->GetSelectedRow();
+ int max = m_list->GetItemCount();
+
+ if (row == max-1) { // Wrap the selection.
+ m_list->SetSelectedRow(0);
+ return true;
+ }
+
+ if (full_service) {
+ m_list->SetSelectedRow(row+1);
+ return true;
+ }
+
+ return false;
+}
+
+bool CurrentTabsPopup::WrapToPrevItem(bool full_service) {
+ // Wrap to bottom of the list if needed.
+ int row = m_list->GetSelectedRow();
+
+ if (row == 0) { // Wrap the selection.
+ int max = m_list->GetItemCount();
+ m_list->SetSelectedRow(max-1);
+ return true;
+ }
+
+ if (full_service) {
+ m_list->SetSelectedRow(row-1);
+ return true;
+ }
+
+ return false;
+}
+
+void CurrentTabsPopup::OnMouseLeftDown(wxMouseEvent& event) {
+ wxPoint where = event.GetPosition();
+ wxLogDebug(_("%d,%d"), where.x, where.y);
+
+ // If we have capture and click outside the window, then dismiss as a CANCEL
+ if (HasCapture()) {
+ if (where.x < 0 || where.y < 0 || this->GetSize().x < where.x || this->GetSize().y < where.y) {
+ ReleaseMouse();
+ EndModal(wxID_CANCEL);
+ }
+ }
+}
+
+void CurrentTabsPopup::SelectRow(int row) {
+ int max = m_list->GetItemCount();
+ if (row < max) {
+ m_selectedTabIndex = row;
+ EndModal(wxID_OK);
+ }
+}
+
+void CurrentTabsPopup::OnItemActivated(wxListEvent& WXUNUSED(event)) {
+ long itemIndex = m_list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+ if (itemIndex == -1) {
+ EndModal(wxID_CANCEL);
+ }
+ else {
+ m_selectedTabIndex = itemIndex;
+ EndModal(wxID_OK);
+ }
+}
View
28 src/CurrentTabsPopup.h
@@ -3,7 +3,7 @@
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
- #include <wx/wx.h>
+#include <wx/wx.h>
#endif
#include <vector>
@@ -25,31 +25,19 @@ class CurrentTabsPopup: public wxDialog {
int GetSelectedTabIndex() const;
-private:
- enum Columns {
- Number = 0,
- Filename,
- Path,
- ColumnCount
- };
+ bool WrapToNextItem(bool full_service=false);
+ bool WrapToPrevItem(bool full_service=false);
+ void SelectRow(int row);
+private:
int GetSelectedRow() const;
void SetSelectedRow(int selectedRow);
- class ListEventHandler : public wxEvtHandler {
- public:
- ListEventHandler(CurrentTabsPopup* parent);
-
- private:
- DECLARE_EVENT_TABLE();
- void OnChar(wxKeyEvent& event);
- void OnItemActivated(wxListEvent& event);
-
- CurrentTabsPopup* m_parent;
- };
-
DECLARE_EVENT_TABLE();
void OnShow(wxShowEvent& event);
+ void OnMouseLeftDown(wxMouseEvent& event);
+ void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
+ void OnItemActivated(wxListEvent& event);
wxListCtrlEx* m_list;
int m_selectedTabIndex;
View
5 src/wxListCtrlEx.cpp
@@ -12,10 +12,13 @@ int wxListCtrlEx::GetSelectedRow() const {
return itemIndex;
}
-void wxListCtrlEx::SetSelectedRow(int selectedRow) {
+void wxListCtrlEx::SetSelectedRow(int selectedRow, bool ensure_visible) {
int count = this->GetItemCount();
for (int i = 0; i < count; i++) {
long flags = (i==selectedRow)?wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED : 0;
this->SetItemState(i, flags, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
}
+
+ if (ensure_visible)
+ this->EnsureVisible(selectedRow);
}
View
5 src/wxListCtrlEx.h
@@ -2,8 +2,7 @@
#define __WXLISTCTRLEX_H__
#include <wx/listctrl.h>
-class wxListCtrlEx: public wxListCtrl
-{
+class wxListCtrlEx: public wxListCtrl {
public:
wxListCtrlEx();
wxListCtrlEx(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxLC_ICON, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxListCtrlNameStr);
@@ -13,7 +12,7 @@ class wxListCtrlEx: public wxListCtrl
int GetSelectedRow() const;
/* Sets the given row to be the only selected & focused row. */
- void SetSelectedRow(int selectedRow);
+ void SetSelectedRow(int selectedRow, bool ensure_visible=true);
};
#endif

0 comments on commit 7b335f0

Please sign in to comment.