hrev48638 adds 1 changeset to branch 'master' old head: e3debc9e26e313edfda1e502045ce6b9a1878143 new head: 149ce46d14fb60917b78e8f02343112f0ba96978 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=149ce46+%5Ee3debc9 ---------------------------------------------------------------------------- 149ce46: Update Shortcuts to use standard ColumnListView Patch by atalax (GCI2014) There are some useability changes because our CLV isn't as flexible as the Santa's Gift Bag one. Fixes #11007. [ Adrien Destugues <pulkomandy@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev48638 Commit: 149ce46d14fb60917b78e8f02343112f0ba96978 URL: http://cgit.haiku-os.org/haiku/commit/?id=149ce46 Author: Adrien Destugues <pulkomandy@xxxxxxxxx> Date: Fri Jan 9 08:00:54 2015 UTC Ticket: https://dev.haiku-os.org/ticket/11007 ---------------------------------------------------------------------------- 24 files changed, 393 insertions(+), 4525 deletions(-) src/preferences/shortcuts/EditWindow.cpp | 74 + src/preferences/shortcuts/EditWindow.h | 28 + src/preferences/shortcuts/Jamfile | 17 +- src/preferences/shortcuts/PopUpColumn.cpp | 75 + src/preferences/shortcuts/PopUpColumn.h | 35 + src/preferences/shortcuts/ShortcutsSpec.cpp | 303 +-- src/preferences/shortcuts/ShortcutsSpec.h | 17 +- src/preferences/shortcuts/ShortcutsWindow.cpp | 276 ++- src/preferences/shortcuts/ShortcutsWindow.h | 9 +- src/preferences/shortcuts/clv/CLVColumn.cpp | 228 -- src/preferences/shortcuts/clv/CLVColumn.h | 118 -- .../shortcuts/clv/CLVColumnLabelView.cpp | 810 -------- .../shortcuts/clv/CLVColumnLabelView.h | 97 - src/preferences/shortcuts/clv/CLVListItem.cpp | 204 -- src/preferences/shortcuts/clv/CLVListItem.h | 82 - src/preferences/shortcuts/clv/Colors.h | 54 - src/preferences/shortcuts/clv/ColumnListView.cpp | 1942 ------------------ src/preferences/shortcuts/clv/ColumnListView.h | 262 --- src/preferences/shortcuts/clv/MouseWatcher.cpp | 91 - src/preferences/shortcuts/clv/MouseWatcher.h | 60 - .../shortcuts/clv/PrefilledBitmap.cpp | 28 - src/preferences/shortcuts/clv/PrefilledBitmap.h | 28 - .../shortcuts/clv/ScrollViewCorner.cpp | 45 - src/preferences/shortcuts/clv/ScrollViewCorner.h | 35 - ---------------------------------------------------------------------------- diff --git a/src/preferences/shortcuts/EditWindow.cpp b/src/preferences/shortcuts/EditWindow.cpp new file mode 100644 index 0000000..e2e08a6 --- /dev/null +++ b/src/preferences/shortcuts/EditWindow.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Josef Gajdusek + */ + + +#include "EditWindow.h" + +#include <math.h> + +#include <Button.h> +#include <LayoutBuilder.h> +#include <TextControl.h> +#include <String.h> +#include <StringView.h> + +#include "ShortcutsWindow.h" + + +EditWindow::EditWindow(const char* placeholder, uint32 flags) + : + BWindow(BRect(0, 0, 0, 0), "", B_MODAL_WINDOW, flags) +{ + fTextControl = new BTextControl("", placeholder, NULL); + + BButton* okButton = new BButton("Ok", new BMessage(B_CONTROL_MODIFIED)); + okButton->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_TOP)); + SetDefaultButton(okButton); + + BLayoutBuilder::Group<>(this, B_VERTICAL) + .SetInsets(B_USE_WINDOW_INSETS) + .Add(fTextControl) + .Add(okButton); +} + + +void +EditWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case B_CONTROL_MODIFIED: + delete_sem(fSem); + break; + default: + BWindow::MessageReceived(message); + break; + } +} + + +BString +EditWindow::Go() +{ + fSem = create_sem(0, "EditSem"); + if (fSem < B_OK) { + Quit(); + return ""; + } + + BSize psize = GetLayout()->PreferredSize(); + ResizeTo(max_c(be_plain_font->StringWidth(fTextControl->Text()) * 1.5, + psize.Width()), + psize.Height()); + Show(); + CenterOnScreen(); + + acquire_sem(fSem); + if (Lock()) + Quit(); + return fTextControl->Text(); +} diff --git a/src/preferences/shortcuts/EditWindow.h b/src/preferences/shortcuts/EditWindow.h new file mode 100644 index 0000000..99e88f3 --- /dev/null +++ b/src/preferences/shortcuts/EditWindow.h @@ -0,0 +1,28 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Josef Gajdusek + */ + +#ifndef EDITWINDOW_H +#define EDITWINDOW_H + +#include <Window.h> + +class BTextControl; + +class EditWindow : public BWindow { +public: + EditWindow(const char* placeholder, uint32 flags); + + void MessageReceived(BMessage* message); + BString Go(); + +private: + sem_id fSem; + BTextControl* fTextControl; +}; + +#endif // EDITWINDOW_H diff --git a/src/preferences/shortcuts/Jamfile b/src/preferences/shortcuts/Jamfile index 6ac4a3e..cf9e4b3 100644 --- a/src/preferences/shortcuts/Jamfile +++ b/src/preferences/shortcuts/Jamfile @@ -1,5 +1,7 @@ SubDir HAIKU_TOP src preferences shortcuts ; +UsePrivateHeaders interface ; + SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src preferences shortcuts clv ] ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons input_server filters shortcut_catcher ] ; @@ -7,19 +9,12 @@ Preference Shortcuts : main.cpp MetaKeyStateMap.cpp ShortcutsApp.cpp - ShortcutsSpec.cpp ShortcutsWindow.cpp + ShortcutsSpec.cpp + PopUpColumn.cpp + EditWindow.cpp -# clv files - CLVColumn.cpp - CLVColumnLabelView.cpp - CLVListItem.cpp - ColumnListView.cpp - MouseWatcher.cpp - PrefilledBitmap.cpp - ScrollViewCorner.cpp - - : be localestub tracker libshortcuts_shared.a [ TargetLibstdc++ ] + : be localestub tracker libshortcuts_shared.a libcolumnlistview.a [ TargetLibstdc++ ] : Shortcuts.rdef ; diff --git a/src/preferences/shortcuts/PopUpColumn.cpp b/src/preferences/shortcuts/PopUpColumn.cpp new file mode 100644 index 0000000..e7f5b1e --- /dev/null +++ b/src/preferences/shortcuts/PopUpColumn.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Josef Gajdusek + */ + + +#include "PopUpColumn.h" + +#include <PopUpMenu.h> +#include <MenuItem.h> +#include <Window.h> + +#include "EditWindow.h" +#include "ShortcutsWindow.h" + +PopUpColumn::PopUpColumn(BPopUpMenu* menu, const char* name, float width, + float minWidth, float maxWidth, uint32 truncate, bool editable, + bool cycle, int cycleInit, alignment align) + : + BStringColumn(name, width, minWidth, maxWidth, truncate, align), + fEditable(editable), + fCycle(cycle), + fCycleInit(cycleInit), + fMenu(menu) +{ + SetWantsEvents(true); +} + + +PopUpColumn::~PopUpColumn() +{ + delete fMenu; +} + +void +PopUpColumn::MouseDown(BColumnListView* parent, BRow* row, BField* field, + BRect fieldRect, BPoint point, uint32 buttons) +{ + if ((buttons & B_SECONDARY_MOUSE_BUTTON) + || (buttons & B_PRIMARY_MOUSE_BUTTON && (fEditable || fCycle))) { + BMessage* msg = new BMessage(ShortcutsWindow::HOTKEY_ITEM_MODIFIED); + msg->SetInt32("row", parent->IndexOf(row)); + msg->SetInt32("column", LogicalFieldNum()); + if (buttons & B_SECONDARY_MOUSE_BUTTON) { + BMenuItem* selected = fMenu->Go(parent->ConvertToScreen(point)); + if (selected) { + msg->SetString("text", selected->Label()); + parent->Window()->PostMessage(msg); + } + } + if (buttons & B_PRIMARY_MOUSE_BUTTON && row->IsSelected()) { + BStringField* stringField = static_cast<BStringField*>(field); + if (fEditable) { + EditWindow* edit = new EditWindow(stringField->String(), 0); + msg->SetString("text", edit->Go()); + } else if (fCycle) { + BMenuItem* item; + for (int i = 0; (item = fMenu->ItemAt(i)) != NULL; i++) + if (strcmp(stringField->String(), item->Label()) == 0) { + item = fMenu->ItemAt((i + 1) % fMenu->CountItems()); + break; + } + if (item == NULL) + item = fMenu->ItemAt(fCycleInit); + msg->SetString("text", item->Label()); + } + parent->Window()->PostMessage(msg); + } + } + BStringColumn::MouseDown(parent, row, field, fieldRect, point, buttons); +} + diff --git a/src/preferences/shortcuts/PopUpColumn.h b/src/preferences/shortcuts/PopUpColumn.h new file mode 100644 index 0000000..2b3e8fb --- /dev/null +++ b/src/preferences/shortcuts/PopUpColumn.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Josef Gajdusek + */ +#ifndef POPUPCOLUMN_H +#define POPUPCOLUMN_H + +#include <ColumnTypes.h> + +class BPopUpMenu; + +class PopUpColumn : public BStringColumn { +public: + PopUpColumn(BPopUpMenu* menu, const char* name, + float width, float minWidth, float maxWidth, + uint32 truncate, bool editable = false, + bool cycle = false, int cycleInit = 0, + alignment align = B_ALIGN_LEFT); + virtual ~PopUpColumn(); + + void MouseDown(BColumnListView* parent, BRow* row, + BField* field, BRect fieldRect, BPoint point, + uint32 buttons); + +private: + bool fEditable; + bool fCycle; + int fCycleInit; + BPopUpMenu* fMenu; +}; + +#endif // POPUPCOLUMN_H diff --git a/src/preferences/shortcuts/ShortcutsSpec.cpp b/src/preferences/shortcuts/ShortcutsSpec.cpp index 41917c4..b4a651b 100644 --- a/src/preferences/shortcuts/ShortcutsSpec.cpp +++ b/src/preferences/shortcuts/ShortcutsSpec.cpp @@ -14,6 +14,7 @@ #include <Beep.h> #include <Catalog.h> +#include <ColumnTypes.h> #include <Directory.h> #include <Locale.h> #include <NodeInfo.h> @@ -24,8 +25,8 @@ #include "ColumnListView.h" #include "BitFieldTesters.h" -#include "Colors.h" #include "CommandActuators.h" +#include "KeyInfos.h" #include "MetaKeyStateMap.h" #include "ParseCommandLine.h" @@ -42,7 +43,6 @@ static MetaKeyStateMap sMetaMaps[ShortcutsSpec::NUM_META_COLUMNS]; static bool sFontCached = false; static BFont sViewFont; static float sFontHeight; -static BBitmap* sActuatorBitmaps[2]; const char* ShortcutsSpec::sShiftName; const char* ShortcutsSpec::sControlName; @@ -99,35 +99,6 @@ GetNthKeyMap(int which) } -static BBitmap* -MakeActuatorBitmap(bool lit) -{ - BBitmap* map = new BBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE, true); - const rgb_color yellow = {255, 255, 0}; - const rgb_color red = {200, 200, 200}; - const rgb_color black = {0, 0, 0}; - const BPoint points[10] = { - BPoint(8, 0), BPoint(9.8, 5.8), BPoint(16, 5.8), - BPoint(11, 9.0), BPoint(13, 16), BPoint(8, 11), - BPoint(3, 16), BPoint(5, 9.0), BPoint(0, 5.8), - BPoint(6.2, 5.8) }; - - BView* view = new BView(BRect(0, 0, 16, 16), NULL, B_FOLLOW_ALL_SIDES, 0L); - map->AddChild(view); - map->Lock(); - view->SetHighColor(B_TRANSPARENT_32_BIT); - view->FillRect(ICON_BITMAP_RECT); - view->SetHighColor(lit ? yellow : red); - view->FillPolygon(points, 10); - view->SetHighColor(black); - view->StrokePolygon(points, 10); - map->Unlock(); - map->RemoveChild(view); - delete view; - return map; -} - - /*static*/ void ShortcutsSpec::InitializeMetaMaps() { @@ -149,17 +120,13 @@ ShortcutsSpec::InitializeMetaMaps() SetupStandardMap(sMetaMaps[ShortcutsSpec::OPTION_COLUMN_INDEX], sOptionName , B_OPTION_KEY, B_LEFT_OPTION_KEY, B_RIGHT_OPTION_KEY); - - sActuatorBitmaps[0] = MakeActuatorBitmap(false); - sActuatorBitmaps[1] = MakeActuatorBitmap(true); } ShortcutsSpec::ShortcutsSpec(const char* cmd) : - CLVListItem(0, false, false, _height), + BRow(), fCommand(NULL), - fTextOffset(0), fBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE), fLastBitmapName(NULL), fBitmapValid(false), @@ -174,9 +141,8 @@ ShortcutsSpec::ShortcutsSpec(const char* cmd) ShortcutsSpec::ShortcutsSpec(const ShortcutsSpec& from) : - CLVListItem(0, false, false, _height), + BRow(), fCommand(NULL), - fTextOffset(from.fTextOffset), fBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE), fLastBitmapName(NULL), fBitmapValid(false), @@ -188,14 +154,17 @@ ShortcutsSpec::ShortcutsSpec(const ShortcutsSpec& from) SetCommand(from.fCommand); SetSelectedColumn(from.GetSelectedColumn()); + + for (int i = 0; i < from.CountFields(); i++) + SetField(new BStringField( + static_cast<const BStringField*>(from.GetField(i))->String()), i); } ShortcutsSpec::ShortcutsSpec(BMessage* from) : - CLVListItem(0, false, false, _height), + BRow(), fCommand(NULL), - fTextOffset(0), fBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE), fLastBitmapName(NULL), fBitmapValid(false), @@ -221,6 +190,10 @@ ShortcutsSpec::ShortcutsSpec(BMessage* from) printf(CLASS); printf(" Error, no modifiers int32 in archive BMessage!\n"); } + + const char* string; + for (int i = 0; (string = from->GetString("strings", i, NULL)); i++) + SetField(new BStringField(string), i); } @@ -233,7 +206,7 @@ ShortcutsSpec::SetCommand(const char* command) fCommandNul = fCommandLen - 1; fCommand = new char[fCommandLen]; strcpy(fCommand, command); - _UpdateIconBitmap(); + SetField(new BStringField(command), STRING_COLUMN_INDEX); } @@ -253,6 +226,12 @@ ShortcutsSpec::Archive(BMessage* into, bool deep) const into->AddString("class", "ShortcutsSpec"); + for (int i = 0; i < CountFields(); i++) { + const BStringField* field = + static_cast<const BStringField*>(GetField(i)); + into->AddString("strings", field->String()); + } + // These fields are for our prefs panel's benefit only into->AddString("command", fCommand); into->AddInt32("key", fKey); @@ -281,24 +260,8 @@ ShortcutsSpec::Archive(BMessage* into, bool deep) const delete act; into->AddMessage("act", &actMsg); - return ret; -} - -static bool IsValidActuatorName(const char* c); -static bool -IsValidActuatorName(const char* c) -{ - return (strcmp(c, B_TRANSLATE("InsertString")) == 0 - || strcmp(c, B_TRANSLATE("MoveMouse")) == 0 - || strcmp(c, B_TRANSLATE("MoveMouseTo")) == 0 - || strcmp(c, B_TRANSLATE("MouseButton")) == 0 - || strcmp(c, B_TRANSLATE("LaunchHandler")) == 0 - || strcmp(c, B_TRANSLATE("Multi")) == 0 - || strcmp(c, B_TRANSLATE("MouseDown")) == 0 - || strcmp(c, B_TRANSLATE("MouseUp")) == 0 - || strcmp(c, B_TRANSLATE("SendMessage")) == 0 - || strcmp(c, B_TRANSLATE("Beep")) == 0); + return ret; } @@ -339,150 +302,11 @@ ShortcutsSpec::_CacheViewFont(BView* owner) } -void -ShortcutsSpec::DrawItemColumn(BView* owner, BRect item_column_rect, - int32 column_index, bool columnSelected, bool complete) -{ - const float STRING_COLUMN_LEFT_MARGIN = 25.0f; - // 16 for the icon, +9 empty - - rgb_color color; - bool selected = IsSelected(); - if (selected) - color = columnSelected ? BeBackgroundGrey : BeListSelectGrey; - else - color = BeInactiveControlGrey; - owner->SetLowColor(color); - owner->SetDrawingMode(B_OP_COPY); - owner->SetHighColor(color); - owner->FillRect(item_column_rect); - - const char* text = GetCellText(column_index); - - if (text == NULL) - return; - - _CacheViewFont(owner); - // Ensure that sViewFont is configured before using it to calculate - // widths. The lack of this call was causing the initial display of - // columns to be incorrect, with a "jump" as all the columns correct - // themselves upon the first column resize. - - float textWidth = sViewFont.StringWidth(text); - BPoint point; - rgb_color lowColor = color; - - if (column_index == STRING_COLUMN_INDEX) { - // left justified - point.Set(item_column_rect.left + STRING_COLUMN_LEFT_MARGIN, - item_column_rect.top + fTextOffset); - - item_column_rect.left = point.x; - // keep text from drawing into icon area - - // scroll if too wide - float rectWidth = item_column_rect.Width() - STRING_COLUMN_LEFT_MARGIN; - float extra = textWidth - rectWidth; - if (extra > 0.0f) - point.x -= extra; - } else { - if ((column_index < NUM_META_COLUMNS) && (text[0] == '(')) - return; // don't draw for this ... - - if ((column_index <= NUM_META_COLUMNS) && (text[0] == '\0')) - return; // don't draw for this ... - - // centered - point.Set((item_column_rect.left + item_column_rect.right) / 2.0, - item_column_rect.top + fTextOffset); - _CacheViewFont(owner); - point.x -= textWidth / 2.0f; - } - - BRegion Region; - Region.Include(item_column_rect); - owner->ConstrainClippingRegion(&Region); - if (column_index != STRING_COLUMN_INDEX) { - const float KEY_MARGIN = 3.0f; - const float CORNER_RADIUS = 3.0f; - _CacheViewFont(owner); - - // How about I draw a nice "key" background for this one? - BRect textRect(point.x - KEY_MARGIN, (point.y - sFontHeight) - KEY_MARGIN, - point.x + textWidth + KEY_MARGIN - 2.0f, point.y + KEY_MARGIN); - - if (column_index == KEY_COLUMN_INDEX) - lowColor = ReallyLightPurple; - else - lowColor = LightYellow; - - owner->SetHighColor(lowColor); - owner->FillRoundRect(textRect, CORNER_RADIUS, CORNER_RADIUS); - owner->SetHighColor(Black); - owner->StrokeRoundRect(textRect, CORNER_RADIUS, CORNER_RADIUS); - } - - owner->SetHighColor(Black); - owner->SetLowColor(lowColor); - owner->DrawString(text, point); - // with a cursor at the end if highlighted - if (column_index == STRING_COLUMN_INDEX) { - // Draw cursor - if ((columnSelected) && (selected)) { - point.x += textWidth; - point.y += (fTextOffset / 4.0f); - - BPoint pt2 = point; - pt2.y -= fTextOffset; - owner->StrokeLine(point, pt2); - - fCursorPt1 = point; - fCursorPt2 = pt2; - fCursorPtsValid = true; - } - - BRegion bitmapRegion; - item_column_rect.left -= (STRING_COLUMN_LEFT_MARGIN - 4.0f); - item_column_rect.right = item_column_rect.left + 16.0f; - item_column_rect.top += 3.0f; - item_column_rect.bottom = item_column_rect.top + 16.0f; - - bitmapRegion.Include(item_column_rect); - owner->ConstrainClippingRegion(&bitmapRegion); - owner->SetDrawingMode(B_OP_ALPHA); - - if ((fCommand != NULL) && (fCommand[0] == '*')) - owner->DrawBitmap(sActuatorBitmaps[fBitmapValid ? 1 : 0], - ICON_BITMAP_RECT, item_column_rect); - else - // Draw icon, if any - if (fBitmapValid) - owner->DrawBitmap(&fBitmap, ICON_BITMAP_RECT, - item_column_rect); - } - - owner->SetDrawingMode(B_OP_COPY); - owner->ConstrainClippingRegion(NULL); -} - - -void -ShortcutsSpec::Update(BView* owner, const BFont* font) -{ - CLVListItem::Update(owner, font); - font_height FontAttributes; - be_plain_font->GetHeight(&FontAttributes); - float fontHeight = ceil(FontAttributes.ascent) + - ceil(FontAttributes.descent); - fTextOffset = ceil(FontAttributes.ascent) + (Height() - fontHeight) / 2.0; -} - - const char* ShortcutsSpec::GetCellText(int whichColumn) const { const char* temp = ""; // default - switch(whichColumn) { + switch (whichColumn) { case KEY_COLUMN_INDEX: { if ((fKey > 0) && (fKey <= 0xFF)) { @@ -504,6 +328,8 @@ ShortcutsSpec::GetCellText(int whichColumn) const if ((whichColumn >= 0) && (whichColumn < NUM_META_COLUMNS)) temp = sMetaMaps[whichColumn].GetNthStateDesc( fMetaCellStateIndex[whichColumn]); + if (temp[0] == '(') + temp = ""; break; } return temp; @@ -527,7 +353,7 @@ ShortcutsSpec::ProcessColumnMouseClick(int whichColumn) bool ShortcutsSpec::ProcessColumnTextString(int whichColumn, const char* string) { - switch(whichColumn) { + switch (whichColumn) { case STRING_COLUMN_INDEX: SetCommand(string); return true; @@ -536,6 +362,8 @@ ShortcutsSpec::ProcessColumnTextString(int whichColumn, const char* string) case KEY_COLUMN_INDEX: { fKey = FindKeyCode(string); + SetField(new BStringField(GetCellText(whichColumn)), + KEY_COLUMN_INDEX); return true; break; } @@ -669,7 +497,7 @@ ShortcutsSpec::ProcessColumnKeyStroke(int whichColumn, const char* bytes, { bool result = false; - switch(whichColumn) { + switch (whichColumn) { case KEY_COLUMN_INDEX: if (key > -1) { if ((int32)fKey != key) { @@ -681,7 +509,7 @@ ShortcutsSpec::ProcessColumnKeyStroke(int whichColumn, const char* bytes, case STRING_COLUMN_INDEX: { - switch(bytes[0]) { + switch (bytes[0]) { case B_BACKSPACE: case B_DELETE: if (fCommandNul > 0) { @@ -689,13 +517,11 @@ ShortcutsSpec::ProcessColumnKeyStroke(int whichColumn, const char* bytes, fCommand[fCommandNul - 1] = '\0'; fCommandNul--; // note new nul position result = true; - _UpdateIconBitmap(); } break; case B_TAB: if (_AttemptTabCompletion()) { - _UpdateIconBitmap(); result = true; } else beep(); @@ -727,7 +553,6 @@ ShortcutsSpec::ProcessColumnKeyStroke(int whichColumn, const char* bytes, strncat(fCommand, bytes, fCommandLen); fCommandNul += newCharLen; result = true; - _UpdateIconBitmap(); } } } @@ -787,75 +612,9 @@ ShortcutsSpec::ProcessColumnKeyStroke(int whichColumn, const char* bytes, result = true; } - return result; -} - + SetField(new BStringField(GetCellText(whichColumn)), whichColumn); -int -ShortcutsSpec::CLVListItemCompare(const CLVListItem* firstItem, - const CLVListItem* secondItem, int32 keyColumn) -{ - ShortcutsSpec* left = (ShortcutsSpec*) firstItem; - ShortcutsSpec* right = (ShortcutsSpec*) secondItem; - - int result = strcmp(left->GetCellText(keyColumn), - right->GetCellText(keyColumn)); - - return result > 0 ? 1 : (result == 0 ? 0 : -1); -} - - -void -ShortcutsSpec::Pulse(BView* owner) -{ - if ((fCursorPtsValid)&&(owner->Window()->IsActive())) { - rgb_color prevColor = owner->HighColor(); - rgb_color backgroundColor = (GetSelectedColumn() == - STRING_COLUMN_INDEX) ? BeBackgroundGrey : BeListSelectGrey; - rgb_color barColor = ((GetSelectedColumn() == STRING_COLUMN_INDEX) - && ((system_time() % 1000000) > 500000)) ? Black : backgroundColor; - owner->SetHighColor(barColor); - owner->StrokeLine(fCursorPt1, fCursorPt2); - owner->SetHighColor(prevColor); - } -} - - -void -ShortcutsSpec::_UpdateIconBitmap() -{ - BString firstWord = ParseArgvZeroFromString(fCommand); - - // we only need to change if the first word has changed... - if (fLastBitmapName == NULL || firstWord.Length() == 0 - || firstWord.Compare(fLastBitmapName)) { - if (firstWord.ByteAt(0) == '*') - fBitmapValid = IsValidActuatorName(&firstWord.String()[1]); - else { - fBitmapValid = false; - // default until we prove otherwise - - if (firstWord.Length() > 0) { - delete [] fLastBitmapName; - fLastBitmapName = new char[firstWord.Length() + 1]; - strcpy(fLastBitmapName, firstWord.String()); - - BEntry progEntry(fLastBitmapName, true); - if ((progEntry.InitCheck() == B_NO_ERROR) - && (progEntry.Exists())) { - BNode progNode(&progEntry); - if (progNode.InitCheck() == B_NO_ERROR) { - BNodeInfo progNodeInfo(&progNode); - if ((progNodeInfo.InitCheck() == B_NO_ERROR) - && (progNodeInfo.GetTrackerIcon(&fBitmap, B_MINI_ICON) - == B_NO_ERROR)) { - fBitmapValid = fBitmap.IsValid(); - } - } - } - } - } - } + return result; } diff --git a/src/preferences/shortcuts/ShortcutsSpec.h b/src/preferences/shortcuts/ShortcutsSpec.h index 289656e..d43658a 100644 --- a/src/preferences/shortcuts/ShortcutsSpec.h +++ b/src/preferences/shortcuts/ShortcutsSpec.h @@ -12,7 +12,7 @@ #include <Bitmap.h> -#include "CLVListItem.h" +#include <ColumnListView.h> #include "KeyInfos.h" @@ -28,7 +28,7 @@ MetaKeyStateMap& GetNthKeyMap(int which); * the proper GUI display, and the proper BitFieldTester and CommandActuator * object for the ShortcutsCatcher add-on to use. */ -class ShortcutsSpec : public CLVListItem { +class ShortcutsSpec : public BRow, public BArchivable { public: static void InitializeMetaMaps(); @@ -38,19 +38,10 @@ public: ~ShortcutsSpec(); virtual status_t Archive(BMessage* into, bool deep = true) const; - virtual void Pulse(BView* owner); static BArchivable* Instantiate(BMessage* from); - void Update(BView* owner, const BFont* font); const char* GetCellText(int whichColumn) const; void SetCommand(const char* commandStr); - virtual void DrawItemColumn(BView* owner, BRect item_column_rect, - int32 column_index, bool columnSelected, - bool complete); - - static int CLVListItemCompare(const CLVListItem* firstItem, - const CLVListItem* secondItem, int32 keyColumn); - // Returns the name of the Nth Column. static const char* GetColumnName(int index); @@ -84,13 +75,9 @@ private: void _CacheViewFont(BView* owner); bool _AttemptTabCompletion(); - // call this to ensure the icon is up-to-date - void _UpdateIconBitmap(); - char* fCommand; uint32 fCommandLen; // number of bytes in fCommand buffer uint32 fCommandNul; // index of the NUL byte in fCommand - float fTextOffset; // icon for associated program. Invalid if none available. BBitmap fBitmap; diff --git a/src/preferences/shortcuts/ShortcutsWindow.cpp b/src/preferences/shortcuts/ShortcutsWindow.cpp index 953daaa..6cc3aa6 100644 --- a/src/preferences/shortcuts/ShortcutsWindow.cpp +++ b/src/preferences/shortcuts/ShortcutsWindow.cpp @@ -19,11 +19,14 @@ #include <Button.h> #include <Catalog.h> #include <Clipboard.h> +#include <ColumnListView.h> +#include <ColumnTypes.h> #include <ControlLook.h> #include <File.h> #include <FilePanel.h> #include <FindDirectory.h> #include <Input.h> +#include <LayoutBuilder.h> #include <Locale.h> #include <Message.h> #include <Menu.h> @@ -38,11 +41,11 @@ #include <String.h> #include <SupportDefs.h> -#include "ColumnListView.h" - +#include "EditWindow.h" #include "KeyInfos.h" #include "MetaKeyStateMap.h" #include "ParseCommandLine.h" +#include "PopUpColumn.h" #include "ShortcutsFilterConstants.h" #include "ShortcutsSpec.h" @@ -113,10 +116,6 @@ ShortcutsWindow::ShortcutsWindow() float spacing = be_control_look->DefaultItemSpacing(); - BView* top = new BView(Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0); - top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - AddChild(top); - BMenuBar* menuBar = new BMenuBar(BRect(0, 0, 0, 0), "Menu Bar"); BMenu* fileMenu = new BMenu(B_TRANSLATE("File")); @@ -136,23 +135,14 @@ ShortcutsWindow::ShortcutsWindow() new BMessage(B_QUIT_REQUESTED), 'Q')); menuBar->AddItem(fileMenu); - top->AddChild(menuBar); - BRect tableBounds = Bounds(); tableBounds.top = menuBar->Bounds().bottom + 1; tableBounds.right -= B_V_SCROLL_BAR_WIDTH; tableBounds.bottom -= B_H_SCROLL_BAR_HEIGHT; - BScrollView* containerView; - fColumnListView = new ColumnListView(tableBounds, &containerView, NULL, - B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, - B_SINGLE_SELECTION_LIST, true, true, true, B_NO_BORDER); - - fColumnListView->SetEditMessage(new BMessage(HOTKEY_ITEM_MODIFIED), - BMessenger(this)); + fColumnListView = new BColumnListView(NULL, + B_WILL_DRAW | B_FRAME_EVENTS, B_FANCY_BORDER); - float minListWidth = 0; - // A running total is kept as the columns are created. float cellWidth = be_plain_font->StringWidth("Either") + 20; // ShortcutsSpec does not seem to translate the string "Either". @@ -160,17 +150,17 @@ ShortcutsWindow::ShortcutsWindow() const char* name = ShortcutsSpec::GetColumnName(i); float headerWidth = be_plain_font->StringWidth(name) + 20; float width = max_c(headerWidth, cellWidth); - minListWidth += width + 1; - fColumnListView->AddColumn( - new CLVColumn(name, CreateMetaPopUp(i), width, CLV_SORT_KEYABLE)); + fColumnListView->AddColumn(new PopUpColumn(CreateMetaPopUp(i), name, + width, width - 1, width * 1.5, B_TRUNCATE_END, false, true, 1), + fColumnListView->CountColumns()); } float keyCellWidth = be_plain_font->StringWidth("Caps Lock") + 20; - fColumnListView->AddColumn(new CLVColumn(B_TRANSLATE("Key"), - CreateKeysPopUp(), keyCellWidth, CLV_SORT_KEYABLE)); - minListWidth += keyCellWidth + 1; - + fColumnListView->AddColumn(new PopUpColumn(CreateKeysPopUp(), + B_TRANSLATE("Key"), keyCellWidth, keyCellWidth - 10, + keyCellWidth + 30, B_TRUNCATE_END), + fColumnListView->CountColumns()); BPopUpMenu* popup = new BPopUpMenu(NULL, false); popup->AddItem(new BMenuItem( B_TRANSLATE("(Choose application with file requester)"), NULL)); @@ -190,15 +180,12 @@ ShortcutsWindow::ShortcutsWindow() popup->AddItem(new BMenuItem( B_TRANSLATE("*SendMessage application/x-vnd.Be-TRAK 'Tfnd'"), NULL)); popup->AddItem(new BMenuItem(B_TRANSLATE("*Beep"), NULL)); - fColumnListView->AddColumn(new CLVColumn(B_TRANSLATE("Application"), popup, - 323.0, CLV_SORT_KEYABLE)); - minListWidth += 323.0 + 1; - minListWidth += B_V_SCROLL_BAR_WIDTH; - - fColumnListView->SetSortFunction(ShortcutsSpec::CLVListItemCompare); - top->AddChild(containerView); + fColumnListView->AddColumn(new PopUpColumn(popup, B_TRANSLATE("Application"), + 300.0, 223.0, 324.0, B_TRUNCATE_END, true), + fColumnListView->CountColumns()); fColumnListView->SetSelectionMessage(new BMessage(HOTKEY_ITEM_SELECTED)); + fColumnListView->SetSelectionMode(B_SINGLE_SELECTION_LIST); fColumnListView->SetTarget(this); fAddButton = new BButton(BRect(0, 0, 0, 0), "add", @@ -207,7 +194,6 @@ ShortcutsWindow::ShortcutsWindow() fAddButton->ResizeToPreferred(); fAddButton->MoveBy(spacing, Bounds().bottom - fAddButton->Bounds().bottom - spacing); - top->AddChild(fAddButton); fRemoveButton = new BButton(BRect(0, 0, 0, 0), "remove", B_TRANSLATE("Remove selected shortcut"), @@ -215,7 +201,6 @@ ShortcutsWindow::ShortcutsWindow() fRemoveButton->ResizeToPreferred(); fRemoveButton->MoveBy(fAddButton->Frame().right + spacing, Bounds().bottom - fRemoveButton->Bounds().bottom - spacing); - top->AddChild(fRemoveButton); fRemoveButton->SetEnabled(false); @@ -225,24 +210,9 @@ ShortcutsWindow::ShortcutsWindow() fSaveButton->ResizeToPreferred(); fSaveButton->MoveBy(Bounds().right - fSaveButton->Bounds().right - spacing, Bounds().bottom - fSaveButton->Bounds().bottom - spacing); - top->AddChild(fSaveButton); fSaveButton->SetEnabled(false); - containerView->ResizeBy(0, - -(fAddButton->Bounds().bottom + 2 * spacing + 2)); - - float minButtonBarWidth = fRemoveButton->Frame().right - + fSaveButton->Bounds().right + 2 * spacing; - float minWidth = max_c(minListWidth, minButtonBarWidth); - - float menuBarHeight = menuBar->Bounds().bottom; - float buttonBarHeight = Bounds().bottom - containerView->Frame().bottom; - float minHeight = menuBarHeight + 200 + buttonBarHeight; - - SetSizeLimits(minWidth, MAX_WIDTH, minHeight, MAX_HEIGHT); - // SetSizeLimits() will resize the window to the minimum size. - CenterOnScreen(); entry_ref windowSettingsRef; @@ -265,6 +235,26 @@ ShortcutsWindow::ShortcutsWindow() // tell ourselves to load this file if it exists } + fColumnListView->ResizeAllColumnsToPreferred(); + + BLayoutBuilder::Group<>(this, B_VERTICAL, 0) + .Add(menuBar) + .AddGroup(B_VERTICAL) + .SetInsets(B_USE_WINDOW_INSETS) + .Add(fColumnListView) + .AddGroup(B_HORIZONTAL) + .AddGroup(B_HORIZONTAL) + .SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP)) + .Add(fAddButton) + .Add(fRemoveButton) + .End() + .AddGroup(B_HORIZONTAL) + .SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_TOP)) + .Add(fSaveButton) + .End() + .End() + .End(); + Show(); } @@ -291,7 +281,7 @@ ShortcutsWindow::QuitRequested() alert->SetShortcut(0, B_ESCAPE); alert->SetShortcut(1, 'd'); alert->SetShortcut(2, 's'); - switch(alert->Go()) { + switch (alert->Go()) { case 0: result = false; break; @@ -311,7 +301,7 @@ ShortcutsWindow::QuitRequested() B_TRANSLATE("Oh no")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); - result = true; //quit anyway + result = true; // quit anyway } } else { PostMessage(SAVE_KEYSET); @@ -361,9 +351,9 @@ ShortcutsWindow::_SaveKeySet(BEntry& saveEntry) return false; BMessage saveMessage; - for (int i = 0; i < fColumnListView->CountItems(); i++) { + for (int i = 0; i < fColumnListView->CountRows(); i++) { BMessage next; - if (((ShortcutsSpec*)fColumnListView->ItemAt(i))->Archive(&next) + if (((ShortcutsSpec*)fColumnListView->RowAt(i))->Archive(&next) == B_OK) { saveMessage.AddMessage("spec", &next); } else @@ -392,7 +382,7 @@ ShortcutsWindow::_LoadKeySet(const BMessage& loadMessage) ShortcutsSpec* spec = (ShortcutsSpec*)ShortcutsSpec::Instantiate(&message); if (spec != NULL) - fColumnListView->AddItem(spec); + fColumnListView->AddRow(spec); else printf("_LoadKeySet: Error parsing spec!\n"); } @@ -428,7 +418,7 @@ ShortcutsWindow::_SaveWindowSettings(BEntry& saveEntry) saveMsg.AddRect("window frame", Frame()); for (int i = 0; i < fColumnListView->CountColumns(); i++) { - CLVColumn* column = fColumnListView->ColumnAt(i); + BColumn* column = fColumnListView->ColumnAt(i); saveMsg.AddFloat("column width", column->Width()); } @@ -457,7 +447,7 @@ ShortcutsWindow::_LoadWindowSettings(const BMessage& loadMessage) } for (int i = 0; i < fColumnListView->CountColumns(); i++) { - CLVColumn* column = fColumnListView->ColumnAt(i); + BColumn* column = fColumnListView->ColumnAt(i); float columnWidth; if (loadMessage.FindFloat("column width", i, &columnWidth) == B_OK) column->SetWidth(max_c(column->Width(), columnWidth)); @@ -473,26 +463,27 @@ ShortcutsWindow::_AddNewSpec(const char* defaultCommand) _MarkKeySetModified(); ShortcutsSpec* spec; - int curSel = fColumnListView->CurrentSelection(); - if (curSel >= 0) { - spec = new ShortcutsSpec(*((ShortcutsSpec*) - fColumnListView->ItemAt(curSel))); - - if (defaultCommand) - spec->SetCommand(defaultCommand); - } else - spec = new ShortcutsSpec(defaultCommand ? defaultCommand : ""); - - fColumnListView->AddItem(spec); - fColumnListView->Select(fColumnListView->CountItems() - 1); - fColumnListView->ScrollToSelection(); + BRow* curSel = fColumnListView->CurrentSelection(); + if (curSel) + spec = new ShortcutsSpec(*((ShortcutsSpec*)curSel)); + else { + spec = new ShortcutsSpec(""); + for (int i = 0; i < fColumnListView->CountColumns(); i++) + spec->SetField(new BStringField(""), i); + } + + fColumnListView->AddRow(spec); + fColumnListView->AddToSelection(spec); + fColumnListView->ScrollTo(spec); + if (defaultCommand) + spec->SetCommand(defaultCommand); } void ShortcutsWindow::MessageReceived(BMessage* message) { - switch(message->what) { + switch (message->what) { case OPEN_KEYSET: case APPEND_KEYSET: fLastOpenWasAppend = (message->what == APPEND_KEYSET); @@ -531,7 +522,7 @@ ShortcutsWindow::MessageReceived(BMessage* message) BEntry entry(&ref); if (entry.InitCheck() == B_OK) { BPath path(&entry); - + if (path.InitCheck() == B_OK) { // Add a new item with the given path. BString str(path.Path()); @@ -570,13 +561,14 @@ ShortcutsWindow::MessageReceived(BMessage* message) } } } - + if (fLastOpenWasAppend == false) { // Clear the menu... - while (ShortcutsSpec* item - = ((ShortcutsSpec*) - fColumnListView->RemoveItem((int32)0))) { - delete item; + while (fColumnListView->CountRows()) { + ShortcutsSpec* row = + static_cast<ShortcutsSpec*>(fColumnListView->RowAt(0)); + fColumnListView->RemoveRow(row); + delete row; } } @@ -604,18 +596,18 @@ ShortcutsWindow::MessageReceived(BMessage* message) // these messages come from the pop-up menu of the Applications column case SELECT_APPLICATION: { - int csel = fColumnListView->CurrentSelection(); - if (csel >= 0) { + ShortcutsSpec* row = + static_cast<ShortcutsSpec*>(fColumnListView->CurrentSelection()); + if (row != NULL) { entry_ref aref; if (message->FindRef("refs", &aref) == B_OK) { BEntry ent(&aref); if (ent.InitCheck() == B_OK) { BPath path; if ((ent.GetPath(&path) == B_OK) - && (((ShortcutsSpec*)fColumnListView->ItemAt(csel))-> + && (row-> ProcessColumnTextString(ShortcutsSpec::STRING_COLUMN_INDEX, path.Path()))) { - fColumnListView->InvalidateItem(csel); _MarkKeySetModified(); } } @@ -673,26 +665,27 @@ ShortcutsWindow::MessageReceived(BMessage* message) case REMOVE_HOTKEY_ITEM: { - int index = fColumnListView->CurrentSelection(); - if (index >= 0) { - CLVListItem* item = (CLVListItem*) - fColumnListView->ItemAt(index); - fColumnListView->RemoveItem(index); + BRow* item = fColumnListView->CurrentSelection(); + if (item) { + int index = fColumnListView->IndexOf(item); + fColumnListView->RemoveRow(item); delete item; _MarkKeySetModified(); // Rules for new selection: If there is an item at (index), // select it. Otherwise, if there is an item at (index-1), // select it. Otherwise, select nothing. - int num = fColumnListView->CountItems(); + int num = fColumnListView->CountRows(); if (num > 0) { if (index < num) - fColumnListView->Select(index); + fColumnListView->AddToSelection( + fColumnListView->RowAt(index)); else { if (index > 0) index--; - if (index < num) - fColumnListView->Select(index); + if (index < num) + fColumnListView->AddToSelection( + fColumnListView->RowAt(index)); } } } @@ -702,10 +695,10 @@ ShortcutsWindow::MessageReceived(BMessage* message) // Received when the user clicks on the ColumnListView case HOTKEY_ITEM_SELECTED: { - int32 index = -1; - message->FindInt32("index", &index); - bool validItem = (index >= 0); - fRemoveButton->SetEnabled(validItem); + if (fColumnListView->CountRows() > 0) + fRemoveButton->SetEnabled(true); + else + fRemoveButton->SetEnabled(false); break; } @@ -721,20 +714,20 @@ ShortcutsWindow::MessageReceived(BMessage* message) if (row >= 0) { ShortcutsSpec* item = (ShortcutsSpec*) - fColumnListView->ItemAt(row); + fColumnListView->RowAt(row); bool repaintNeeded = false; // default if (message->HasInt32("mouseClick")) { repaintNeeded = item->ProcessColumnMouseClick(column); } else if ((message->FindString("bytes", &bytes) == B_OK) && (message->FindInt32("key", &key) == B_OK)) { - repaintNeeded = item->ProcessColumnKeyStroke(column, + repaintNeeded = item->ProcessColumnKeyStroke(column, bytes, key); } else if (message->FindInt32("unmappedkey", &key) == B_OK) { - repaintNeeded = ((column == item->KEY_COLUMN_INDEX) - && ((key > 0xFF) || (GetKeyName(key) != NULL)) - && (item->ProcessColumnKeyStroke(column, NULL, + repaintNeeded = ((column == item->KEY_COLUMN_INDEX) + && ((key > 0xFF) || (GetKeyName(key) != NULL)) + && (item->ProcessColumnKeyStroke(column, NULL, key))); } else if (message->FindString("text", &bytes) == B_OK) { if ((bytes[0] == '(')&&(bytes[1] == 'C')) { @@ -747,16 +740,15 @@ ShortcutsWindow::MessageReceived(BMessage* message) NULL, 0, false, &message); fSelectPanel->Show(); } - fSelectPanel->SetButtonLabel(B_DEFAULT_BUTTON, + fSelectPanel->SetButtonLabel(B_DEFAULT_BUTTON, B_TRANSLATE("Select")); - } else { + } else repaintNeeded = item->ProcessColumnTextString( column, bytes); - } } - + if (repaintNeeded) { - fColumnListView->InvalidateItem(row); + fColumnListView->Invalidate(row); _MarkKeySetModified(); } } @@ -784,10 +776,6 @@ ShortcutsWindow::_MarkKeySetModified() void ShortcutsWindow::Quit() { - for (int i = fColumnListView->CountItems() - 1; i >= 0; i--) - delete (ShortcutsSpec*)fColumnListView->ItemAt(i); - - fColumnListView->MakeEmpty(); BWindow::Quit(); } @@ -795,29 +783,28 @@ ShortcutsWindow::Quit() void ShortcutsWindow::DispatchMessage(BMessage* message, BHandler* handler) { - switch(message->what) { + switch (message->what) { + case B_SIMPLE_DATA: + MessageReceived(message); + break; + case B_COPY: case B_CUT: if (be_clipboard->Lock()) { - int32 row = fColumnListView->CurrentSelection(); - int32 column = fColumnListView->GetSelectedColumn(); - if ((row >= 0) - && (column == ShortcutsSpec::STRING_COLUMN_INDEX)) { - ShortcutsSpec* spec = (ShortcutsSpec*) - fColumnListView->ItemAt(row); - if (spec) { - BMessage* data = be_clipboard->Data(); - data->RemoveName("text/plain"); - data->AddData("text/plain", B_MIME_TYPE, - spec->GetCellText(column), - strlen(spec->GetCellText(column))); - be_clipboard->Commit(); - - if (message->what == B_CUT) { - spec->ProcessColumnTextString(column, ""); - _MarkKeySetModified(); - fColumnListView->InvalidateItem(row); - } + ShortcutsSpec* row = + static_cast<ShortcutsSpec*>(fColumnListView->CurrentSelection()); + if (row) { + BMessage* data = be_clipboard->Data(); + data->RemoveName("text/plain"); + data->AddData("text/plain", B_MIME_TYPE, + row->GetCellText(ShortcutsSpec::STRING_COLUMN_INDEX), + strlen(row->GetCellText(ShortcutsSpec::STRING_COLUMN_INDEX))); + be_clipboard->Commit(); + + if (message->what == B_CUT) { + row->ProcessColumnTextString( + ShortcutsSpec::STRING_COLUMN_INDEX, ""); + _MarkKeySetModified(); } } be_clipboard->Unlock(); @@ -831,26 +818,35 @@ ShortcutsWindow::DispatchMessage(BMessage* message, BHandler* handler) ssize_t textLen; if (data->FindData("text/plain", B_MIME_TYPE, (const void**) &text, &textLen) == B_OK) { - int32 row = fColumnListView->CurrentSelection(); - int32 column = fColumnListView->GetSelectedColumn(); - if ((row >= 0) - && (column == ShortcutsSpec::STRING_COLUMN_INDEX)) { - ShortcutsSpec* spec = (ShortcutsSpec*) - fColumnListView->ItemAt(row); - if (spec) { - for (ssize_t i = 0; i < textLen; i++) { - char buf[2] = {text[i], 0x00}; - spec->ProcessColumnKeyStroke(column, buf, 0); - } + ShortcutsSpec* row = + static_cast<ShortcutsSpec*>(fColumnListView->CurrentSelection()); + if (row) { + for (ssize_t i = 0; i < textLen; i++) { + char buf[2] = {text[i], 0x00}; + row->ProcessColumnKeyStroke( + ShortcutsSpec::STRING_COLUMN_INDEX, buf, 0); } - fColumnListView->InvalidateItem(row); - _MarkKeySetModified(); } + _MarkKeySetModified(); } be_clipboard->Unlock(); } break; - + + case B_KEY_DOWN: + ShortcutsSpec* selected; + if (message->GetInt32("modifiers", 0) != 0) + BWindow::DispatchMessage(message, handler); + else if (handler == fColumnListView + && (selected = + static_cast<ShortcutsSpec*>(fColumnListView->CurrentSelection()))) { + selected->ProcessColumnTextString( + ShortcutsSpec::KEY_COLUMN_INDEX, + GetKeyName(message->GetInt32("key", 0))); + _MarkKeySetModified(); + } + break; + default: BWindow::DispatchMessage(message, handler); break; diff --git a/src/preferences/shortcuts/ShortcutsWindow.h b/src/preferences/shortcuts/ShortcutsWindow.h index 792ec2d..00d1001 100644 --- a/src/preferences/shortcuts/ShortcutsWindow.h +++ b/src/preferences/shortcuts/ShortcutsWindow.h @@ -10,15 +10,16 @@ #define SHORTCUTS_WINDOW_H +#include <ColumnListView.h> #include <Entry.h> #include <Window.h> -#include "ColumnListView.h" - class BButton; +class BColumnListView; class BFilePanel; class BMessage; +class ShortcutsSpec; // This class defines our preferences/configuration window. class ShortcutsWindow : public BWindow { @@ -69,7 +70,7 @@ private: BButton* fAddButton; BButton* fRemoveButton; BButton* fSaveButton; - ColumnListView* fColumnListView; + BColumnListView* fColumnListView; BFilePanel* fSavePanel; // for saving settings BFilePanel* fOpenPanel; @@ -85,6 +86,8 @@ private: // true iff the file-requester's ref should be appended to current bool fLastOpenWasAppend; + + BRow* fSelectedRow; }; diff --git a/src/preferences/shortcuts/clv/CLVColumn.cpp b/src/preferences/shortcuts/clv/CLVColumn.cpp deleted file mode 100644 index 1b3e635..0000000 --- a/src/preferences/shortcuts/clv/CLVColumn.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 1999-2009 Jeremy Friesner - * Copyright 2009-2014 Haiku, Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Jeremy Friesner - * John Scipione, jscipione@xxxxxxxxx - */ - - -#define CLVColumn_CPP - -#include <string.h> - -#include "CLVColumn.h" -#include "ColumnListView.h" -#include "CLVColumnLabelView.h" - - -CLVColumn::CLVColumn(const char* label, BPopUpMenu* popup, float width, - uint32 flags, float minWidth) -{ - fPopup = popup; - - if (flags & CLV_EXPANDER) { - label = NULL; - width = 20.0; - minWidth = 20.0; - flags &= CLV_NOT_MOVABLE | CLV_LOCK_AT_BEGINNING | CLV_HIDDEN - | CLV_LOCK_WITH_RIGHT; - flags |= CLV_EXPANDER | CLV_NOT_RESIZABLE | CLV_MERGE_WITH_RIGHT; - } - - if (minWidth < 4.0) - minWidth = 4.0; - - if (width < minWidth) - width = minWidth; - - if (label != NULL) { - fLabel = new char[strlen(label) + 1]; - strcpy((char*)fLabel, label); - } else - fLabel = NULL; - - fWidth = width; - fMinWidth = minWidth; - fFlags = flags; - fPushedByExpander = false; - fParent = NULL; - fSortMode = SORT_MODE_NONE; -} - - -CLVColumn::~CLVColumn() -{ - delete[] fLabel; - if (fParent != NULL) - fParent->RemoveColumn(this); - - delete fPopup; -} - - -float -CLVColumn::Width() const -{ - return fWidth; -} - - -void -CLVColumn::SetWidth(float width) -{ - if(width < fMinWidth) - width = fMinWidth; - - if(width != fWidth) { - float oldWidth = fWidth; - fWidth = width; - if (IsShown() && fParent != NULL) { - BWindow* parentWindow = fParent->Window(); - if (parentWindow != NULL) - parentWindow->Lock(); - - // figure out the area after this column to scroll - BRect ColumnViewBounds = fParent->fColumnLabelView->Bounds(); - BRect MainViewBounds = fParent->Bounds(); - BRect sourceArea = ColumnViewBounds; - sourceArea.left = fColumnEnd + 1.0; - BRect destArea = sourceArea; - float delta = width-oldWidth; - destArea.left += delta; - destArea.right += delta; - float LimitShift; - if (destArea.right > ColumnViewBounds.right) { - LimitShift = destArea.right-ColumnViewBounds.right; - destArea.right -= LimitShift; - sourceArea.right -= LimitShift; - } - if (destArea.left < ColumnViewBounds.left) { - LimitShift = ColumnViewBounds.left - destArea.left; - destArea.left += LimitShift; - sourceArea.left += LimitShift; - } - - // scroll the area that is being shifted - if(parentWindow) - parentWindow->UpdateIfNeeded(); - - fParent->fColumnLabelView->CopyBits(sourceArea, destArea); - sourceArea.top = MainViewBounds.top; - sourceArea.bottom = MainViewBounds.bottom; - destArea.top = MainViewBounds.top; - destArea.bottom = MainViewBounds.bottom; - fParent->CopyBits(sourceArea, destArea); - - // invalidate the region that got revealed - destArea = ColumnViewBounds; - if (width > oldWidth) { - destArea.left = fColumnEnd + 1.0; - destArea.right = fColumnEnd + delta; - } else { - destArea.left = ColumnViewBounds.right + delta + 1.0; - destArea.right = ColumnViewBounds.right; - } - fParent->fColumnLabelView->Invalidate(destArea); - destArea.top = MainViewBounds.top; - destArea.bottom = MainViewBounds.bottom; - fParent->Invalidate(destArea); - - // invalidate the old or new resize handle as necessary - destArea = ColumnViewBounds; - if (width > oldWidth) - destArea.left = fColumnEnd; - else - destArea.left = fColumnEnd + delta; - - destArea.right = destArea.left; - fParent->fColumnLabelView->Invalidate(destArea); - - // update the column sizes, positions and group positions - fParent->ShiftDragGroup(); - fParent->fColumnLabelView->UpdateDragGroups(); - if(parentWindow) - parentWindow->Unlock(); - } - if (fParent != NULL) { - fParent->ColumnWidthChanged(fParent->fColumnList.IndexOf(this), - fWidth); - } - } -} - - -uint32 -CLVColumn::Flags() const -{ - return fFlags; -} - - -bool -CLVColumn::IsShown() const -{ - if ((fFlags & CLV_HIDDEN) != 0) - return false; - else - return true; -} - - -void -CLVColumn::SetShown(bool show) -{ - bool shown = IsShown(); - if (shown != show) { - if (show) - fFlags &= 0xFFFFFFFF^CLV_HIDDEN; - else - fFlags |= CLV_HIDDEN; - - if (fParent != NULL) { - float updateLeft = fColumnBegin; - BWindow* parentWindow = fParent->Window(); - if (parentWindow != NULL) - parentWindow->Lock(); - - fParent->ShiftDragGroup(); - fParent->fColumnLabelView->UpdateDragGroups(); - if (show) - updateLeft = fColumnBegin; - - BRect area = fParent->fColumnLabelView->Bounds(); - area.left = updateLeft; - fParent->fColumnLabelView->Invalidate(area); - area = fParent->Bounds(); - area.left = updateLeft; - fParent->Invalidate(area); - if ((fFlags & CLV_EXPANDER) != 0) { - if (!show) - fParent->fExpanderColumn = -1; - else - fParent->fExpanderColumn = fParent->IndexOfColumn(this); - } - if (parentWindow != NULL) - parentWindow->Unlock(); - } - } -} - - -CLVSortMode -CLVColumn::SortMode() const -{ - return fSortMode; -} - - -void -CLVColumn::SetSortMode(CLVSortMode mode) -{ - if (fParent != NULL) - fParent->SetSortMode(fParent->IndexOfColumn(this), mode); - else - fSortMode = mode; -} diff --git a/src/preferences/shortcuts/clv/CLVColumn.h b/src/preferences/shortcuts/clv/CLVColumn.h deleted file mode 100644 index 2b77288..0000000 --- a/src/preferences/shortcuts/clv/CLVColumn.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 1999-2009 Jeremy Friesner - * Copyright 2009-2014 Haiku, Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Jeremy Friesner - * John Scipione, jscipione@xxxxxxxxx - */ -#ifndef CLV_COLUMN_H -#define CLV_COLUMN_H - - -#include <support/SupportDefs.h> -#include <interface/PopUpMenu.h> - - -// flags -enum { - CLV_SORT_KEYABLE = 0x00000001, - // Can be used as the sorting key - CLV_NOT_MOVABLE = 0x00000002, - // Column can't be moved by user - CLV_NOT_RESIZABLE = 0x00000004, - // Column can't be resized by user - CLV_LOCK_AT_BEGINNING = 0x00000008, - // Movable columns may not be placed or moved by the user - // into a position before this one - CLV_LOCK_AT_END = 0x00000010, - // Movable columns may not be placed or moved by the user - // into a position after this one - CLV_HIDDEN = 0x00000020, - // This column is hidden initially - CLV_MERGE_WITH_RIGHT = 0x00000040, - // Merge this column label with the one that follows it. - CLV_LOCK_WITH_RIGHT = 0x00000080, - // Lock this column to the one that follows it such that - // if the column to the right is moved by the user, this - // one will move with it and vice versa - CLV_EXPANDER = 0x00000100, - // Column contains an expander. You may only use one - // expander in a ColumnListView, and an expander may not be - // added to a non-hierarchal ColumnListView. It may not - // have a label. Its width is automatically set to 20.0. - // The only flags that affect it are CLV_NOT_MOVABLE, - // CLV_LOCK_AT_BEGINNING, CLV_NOT_SHOWN and - // CLV_LOCK_WITH_RIGHT. The others are set for you: - // CLV_NOT_RESIZABLE | CLV_MERGE_WITH_RIGHT - CLV_PUSH_PASS = 0x00000200 - // Causes this column, if pushed by an expander to the - // left, to pass that push on and also push the next - // column to the right. -}; - -enum CLVSortMode { - SORT_MODE_ASCENDING, - SORT_MODE_DESCENDING, - SORT_MODE_NONE -}; - - -class ColumnListView; -class CLVColumn; -class CLVListItem; - - -class CLVColumn { -public: - CLVColumn(const char* label, - BPopUpMenu* popup = NULL, - float width = 20.0, uint32 flags = 0L, - float min_width = 20.0); - virtual ~CLVColumn(); - - // Archival stuff - /* Not implemented yet - CLVColumn(BMessage* archive); - static CLVColumn* Instantiate(BMessage* data); - virtual status_t Archive(BMessage* data, bool deep = true) const; - */ - - // Functions - float Width() const; - virtual void SetWidth(float width); - // Can be overridden to detect changes to the column width - // however since you are probably overriding ColumnListView - // and dealing with an array of columns anyway, it is - // probably more useful to override - // ColumnListView::ColumnWidthChanged to detect changes to - // column widths - uint32 Flags() const; - bool IsShown() const; - void SetShown(bool show); - CLVSortMode SortMode() const; - void SetSortMode(CLVSortMode mode); - const char* GetLabel() const { return fLabel; } - BPopUpMenu* GetPopup() { return fPopup; } - -private: - friend class ColumnListView; - friend class CLVColumnLabelView; - friend class CLVListItem; - - const char* fLabel; - float fWidth; - float fMinWidth; - float fColumnBegin; - float fColumnEnd; - uint32 fFlags; - bool fPushedByExpander; - CLVSortMode fSortMode; - ColumnListView* fParent; - BPopUpMenu* fPopup; - // added by jaf -}; - - -#endif // CLV_COLUMN_H diff --git a/src/preferences/shortcuts/clv/CLVColumnLabelView.cpp b/src/preferences/shortcuts/clv/CLVColumnLabelView.cpp deleted file mode 100644 index 3567bce..0000000 --- a/src/preferences/shortcuts/clv/CLVColumnLabelView.cpp +++ /dev/null @@ -1,810 +0,0 @@ -/* - * Copyright 1999-2009 Jeremy Friesner - * Copyright 2009-2014 Haiku, Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Jeremy Friesner - * John Scipione, jscipione@xxxxxxxxx - */ - - -#define CLVColumnLabelView_CPP - -#include "CLVColumnLabelView.h" -#include "ColumnListView.h" -#include "CLVColumn.h" -#include "MouseWatcher.h" - - -CLVColumnLabelView::CLVColumnLabelView(BRect frame, ColumnListView* parent, - const BFont* font) - : - BView(frame, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, - B_WILL_DRAW | B_FRAME_EVENTS), - fDragGroupsList(10) -{ - SetFont(font); - SetViewColor(BeBackgroundGrey); - SetLowColor(BeBackgroundGrey); - SetHighColor(Black); - fParent = parent; - fDisplayList = &fParent->fColumnDisplayList; - fColumnClicked = NULL; - fColumnDragging = false; - fColumnResizing = false; - font_height fontAttributes; - font->GetHeight(&fontAttributes); - fFontAscent = ceil(fontAttributes.ascent); -} - - -CLVColumnLabelView::~CLVColumnLabelView() -{ - int32 groupCount = fDragGroupsList.CountItems(); - for (int32 i = 0; i < groupCount; i++) - fDragGroupsList.RemoveItem(int32(0)); -} - - -void -CLVColumnLabelView::Draw(BRect updateRect) -{ - BRegion clippingRegion; - GetClippingRegion(&clippingRegion); - BRect bounds = Bounds(); - - // draw each column label in turn - float columnBegin = 0.0; - float columnEnd = -1.0; - bool shouldMergeWithLeft = false; - int32 columnCount = fDisplayList->CountItems(); - BPoint startingPoint; - BPoint stoppingPoint; - for (int32 i = 0; i < columnCount; i++) { - CLVColumn* column = (CLVColumn*)fDisplayList->ItemAt(i); - if (column->IsShown()) { - // figure out where this column is - columnBegin = column->fColumnBegin; - columnEnd = column->fColumnEnd; - // start by figuring out if this column will merge - // with a shown column to the right - bool shouldMergeWithRight = false; - if ((column->fFlags & CLV_MERGE_WITH_RIGHT) != 0) { - for (int32 j = i + 1; j < columnCount; j++) { - CLVColumn* nextColumn = (CLVColumn*)fDisplayList->ItemAt(j); - if (nextColumn->IsShown()) { - // next column is shown - shouldMergeWithRight = true; - break; - } else if ((nextColumn->fFlags & CLV_MERGE_WITH_RIGHT) - == 0) { - // next column is not shown and doesn't - // pass on the merge - break; - } - } - } - - if (clippingRegion.Intersects(BRect(columnBegin, - bounds.top, columnEnd, bounds.bottom))) { - // need to draw this column - BeginLineArray(4); - - // top line - startingPoint.Set(columnBegin, bounds.top); - stoppingPoint.Set(columnEnd - 1.0, bounds.top); - if (shouldMergeWithRight && !(column == fColumnClicked - && fColumnResizing)) { - stoppingPoint.x = columnEnd; - } - AddLine(startingPoint, stoppingPoint, BeHighlight); - - // left line - if (!shouldMergeWithLeft) { - AddLine(BPoint(columnBegin, bounds.top + 1.0), - BPoint(columnBegin, bounds.bottom), BeHighlight); - } - - // bottom line - startingPoint.Set(columnBegin + 1.0, bounds.bottom); - if (shouldMergeWithLeft) - startingPoint.x = columnBegin; - - stoppingPoint.Set(columnEnd - 1.0, bounds.bottom); - if (shouldMergeWithRight && !(column == fColumnClicked - && fColumnResizing)) { - stoppingPoint.x = columnEnd; - } - AddLine(startingPoint, stoppingPoint, BeShadow); - - // right line - if (column == fColumnClicked && fColumnResizing) { - AddLine(BPoint(columnEnd, bounds.top), - BPoint(columnEnd, bounds.bottom), BeFocusBlue); - } else if (!shouldMergeWithRight) { - AddLine(BPoint(columnEnd, bounds.top), - BPoint(columnEnd, bounds.bottom), BeShadow); - } - EndLineArray(); - - // add the label - if (column->fLabel != NULL) { - // limit the clipping region to the interior of the box - BRegion textRegion; - textRegion.Include(BRect(columnBegin + 1.0, - bounds.top + 1.0, columnEnd - 1.0, - bounds.bottom - 1.0)); - ConstrainClippingRegion(&textRegion); - - // draw the label - if (column == fColumnClicked && !fColumnResizing) - SetHighColor(BeFocusBlue); - - SetDrawingMode(B_OP_OVER); - DrawString(column->fLabel, - BPoint(columnBegin + 9.0, - bounds.top + 2.0 + fFontAscent)); - SetDrawingMode(B_OP_COPY); - - // underline if this is a selected sort column - if (fParent->fSortKeyList.HasItem(column) - && column->fSortMode != SORT_MODE_NONE) { - float Width = StringWidth(column->fLabel); - StrokeLine(BPoint(columnBegin + 8.0, - bounds.top + 2.0 + fFontAscent + 2.0), - BPoint(columnBegin + 8.0 + Width, - bounds.top + 2.0 + fFontAscent + 2.0)); - } - if (column == fColumnClicked && !fColumnResizing) - SetHighColor(Black); - - // restore the clipping region - ConstrainClippingRegion(NULL); - } - } - - // set shouldMergeWithLeft flag for the next column to - // the appropriate state - shouldMergeWithLeft = shouldMergeWithRight; - } - } - - // add highlight and shadow to the region after the columns if necessary - if (columnEnd < bounds.right) { - columnBegin = columnEnd + 1.0; - - if (clippingRegion.Intersects(BRect(columnEnd + 1.0, - bounds.top, bounds.right, bounds.bottom))) { - BeginLineArray(3); - - // top line - AddLine(BPoint(columnBegin, bounds.top), - BPoint(bounds.right, bounds.top), BeHighlight); - - // left line - AddLine(BPoint(columnBegin, bounds.top + 1.0), - BPoint(columnBegin, bounds.bottom), BeHighlight); - - // bottom line - startingPoint.Set(columnBegin + 1.0, bounds.bottom); - if (shouldMergeWithLeft) - startingPoint.x = columnBegin; - - stoppingPoint.Set(bounds.right, bounds.bottom); - AddLine(startingPoint, stoppingPoint, BeShadow); - EndLineArray(); - } - } - - // draw the dragging box if necessary - if (fColumnClicked && fColumnDragging) { - float dragOutlineLeft = fPreviousMousePosition.x - - fDragBoxMouseHoldOffset; - float groupBegin = ((CLVDragGroup*)fDragGroupsList.ItemAt( - fDragGroupIndex))->groupBeginIndex; - if (dragOutlineLeft < groupBegin && fSnapGroupBeforeIndex == -1) - dragOutlineLeft = groupBegin; - - if (dragOutlineLeft > groupBegin && fSnapGroupAfterIndex == -1) - dragOutlineLeft = groupBegin; - - float DragOutlineRight = dragOutlineLeft + fDragBoxWidth; - - BeginLineArray(4); - AddLine(BPoint(dragOutlineLeft, bounds.top), - BPoint(DragOutlineRight, bounds.top), BeFocusBlue); - AddLine(BPoint(dragOutlineLeft, bounds.bottom), - BPoint(DragOutlineRight, bounds.bottom), BeFocusBlue); - AddLine(BPoint(dragOutlineLeft, bounds.top + 1.0), - BPoint(dragOutlineLeft, bounds.bottom - 1.0), BeFocusBlue); - AddLine(BPoint(DragOutlineRight, bounds.top + 1.0), - BPoint(DragOutlineRight, bounds.bottom - 1.0), BeFocusBlue); - EndLineArray(); - - fPreviousDragOutlineLeft = dragOutlineLeft; - fPreviousDragOutlineRight = DragOutlineRight; - } -} - - -void -CLVColumnLabelView::MouseDown(BPoint where) -{ - // pay attention only to primary mouse button - bool shouldWatchMouse = false; - BPoint mousePosition; - uint32 buttons; - GetMouse(&mousePosition, &buttons); - if (buttons == B_PRIMARY_MOUSE_BUTTON) { - BRect bounds = Bounds(); - - // Make sure no other column was already clicked. - // If so, just discard the old one and redraw the view. - if (fColumnClicked != NULL) { - Invalidate(); - fColumnClicked = NULL; - } - - // find the column that the user clicked, if any - bool didGrabResizeTab = false; - int32 columnCount = fDisplayList->CountItems(); - int32 i; - CLVColumn* column = NULL; - for (i = 0; i < columnCount; i++) { - column = (CLVColumn*)fDisplayList->ItemAt(i); - if (column->IsShown()) { - float columnBegin = column->fColumnBegin; - float columnEnd = column->fColumnEnd; - if ((where.x >= columnBegin && where.x <= columnEnd) - || ((i == columnCount - 1) && (where.x >= columnBegin))) { - // anything after the rightmost column can drag... jaf - const float resizeTolerance = 5.0f; - // jaf is too clumsy to click on a 2 pixel space. :) - - // user clicked in this column - if (where.x <= columnBegin + resizeTolerance) { - // user clicked the resize tab preceding this column - for (i--; i >= 0; i--) { - column = (CLVColumn*)fDisplayList->ItemAt(i); - if (column->IsShown()) { - didGrabResizeTab = true; - break; - } - } - } else if (where.x >= columnEnd-resizeTolerance) { - // user clicked the resize tab for (after) this column - didGrabResizeTab = true; - } else { - // user clicked in this column - fColumnClicked = (CLVColumn*)fDisplayList->ItemAt(i); - fColumnResizing = false; - fPreviousMousePosition = where; - fMouseClickedPosition = where; - fColumnDragging = false; - SetSnapMinMax(); - fDragBoxMouseHoldOffset = where.x - - ((CLVDragGroup*)fDragGroupsList.ItemAt( - fDragGroupIndex))->groupBeginIndex; - - Invalidate(BRect(columnBegin + 1.0, - bounds.top + 1.0, columnEnd - 1.0, - bounds.bottom - 1.0)); - - // start watching the mouse - shouldWatchMouse = true; - } - break; - } - } - } - - if (didGrabResizeTab) { - // user grabbed a resize tab, check to see if - // resizing this column is allowed - if ((column->fFlags & CLV_NOT_RESIZABLE) == 0) { - fColumnClicked = (CLVColumn*)fDisplayList->ItemAt(i); - fColumnResizing = true; - fPreviousMousePosition = where; - fMouseClickedPosition = where; - fColumnDragging = false; - fResizeMouseHoldOffset = where.x - fColumnClicked->fColumnEnd; - Invalidate(BRect(fColumnClicked->fColumnEnd, bounds.top, - column->fColumnEnd, bounds.bottom)); - - // start watching the mouse - shouldWatchMouse = true; - } - } - } - - if (shouldWatchMouse) { - thread_id MouseWatcherThread = StartMouseWatcher(this); - if (MouseWatcherThread == B_NO_MORE_THREADS - || MouseWatcherThread == B_NO_MEMORY) { - fColumnClicked = NULL; - } - } -} - - -void -CLVColumnLabelView::MessageReceived(BMessage* message) -{ - if (message->what != MW_MOUSE_MOVED && message->what != MW_MOUSE_DOWN - && message->what != MW_MOUSE_UP) { - BView::MessageReceived(message); - } else if (fColumnClicked != NULL) { - BPoint mousePosition; - message->FindPoint("where", &mousePosition); - uint32 buttons; - message->FindInt32("buttons", (int32*)&buttons); - uint32 modifiers; - message->FindInt32("modifiers", (int32*)&modifiers); - BRect bounds; - bounds = Bounds(); - uint32 columnFlags = fColumnClicked->Flags(); - if (buttons == B_PRIMARY_MOUSE_BUTTON) { - // mouse is still held down - if (!fColumnResizing) { - // user is clicking or dragging - if ((mousePosition.x < fMouseClickedPosition.x - 2.0 - || mousePosition.x > fMouseClickedPosition.x + 2.0) - && !fColumnDragging) { - // user is initiating a drag - if ((fDragGroup->flags & CLV_NOT_MOVABLE) != 0) { - // not allowed to drag this column - terminate the click - Invalidate(BRect(fColumnClicked->fColumnBegin, - bounds.top, fColumnClicked->fColumnEnd, - bounds.bottom)); - fColumnClicked = NULL; - } else { - // actually initiate a drag - fColumnDragging = true; - fPreviousDragOutlineLeft = -1.0; - fPreviousDragOutlineRight = -1.0; - } - } - - // now deal with dragging - if (fColumnDragging) { - // user is dragging - if (mousePosition.x < fPreviousMousePosition.x - || mousePosition.x > fPreviousMousePosition.x) { - // mouse moved since I last checked - bounds = Bounds(); - - bool hasColumnSnapped; - do { - // live dragging of columns - hasColumnSnapped = false; - float columnsUpdateLeft = 0; - float columnsUpdateRight = 0; - float MainViewUpdateLeft = 0; - float MainViewUpdateRight = 0; - CLVColumn* lastSwapColumn = NULL; - if (fSnapMin != -1.0 - && mousePosition.x < fSnapMin) { - // shift the group left - columnsUpdateLeft - = fShownGroupBefore->groupBeginIndex; - columnsUpdateRight = fDragGroup->groupEndIndex; - MainViewUpdateLeft = columnsUpdateLeft; - MainViewUpdateRight = columnsUpdateRight; - lastSwapColumn - = fShownGroupBefore->lastColumnShown; - if ((fDragGroup->lastColumnShown->fFlags - & CLV_MERGE_WITH_RIGHT) != 0) { - columnsUpdateRight += 1.0; - } else if ((fShownGroupBefore-> - lastColumnShown->fFlags - & CLV_MERGE_WITH_RIGHT) != 0) { - columnsUpdateRight += 1.0; - } - - ShiftDragGroup(fSnapGroupBeforeIndex); - hasColumnSnapped = true; - } - - if (fSnapMax != -1.0 - && mousePosition.x > fSnapMax) { - // shift the group right - columnsUpdateLeft = fDragGroup->groupBeginIndex; - columnsUpdateRight - = fShownGroupAfter->groupEndIndex; - MainViewUpdateLeft = columnsUpdateLeft; - MainViewUpdateRight = columnsUpdateRight; - lastSwapColumn = fDragGroup->lastColumnShown; - if ((fDragGroup->lastColumnShown->fFlags - & CLV_MERGE_WITH_RIGHT) != 0) { - columnsUpdateRight += 1.0; - } else if ((fShownGroupAfter - ->lastColumnShown->fFlags - & CLV_MERGE_WITH_RIGHT) != 0) { - columnsUpdateRight += 1.0; - } - ShiftDragGroup(fSnapGroupAfterIndex + 1); - hasColumnSnapped = true; - } - - if (hasColumnSnapped) { - // redraw the snapped column labels - Invalidate(BRect(columnsUpdateLeft, - bounds.top, columnsUpdateRight, - bounds.bottom)); - BRect mainBounds = fParent->Bounds(); - // modify MainViewUpdateRight if more - // columns are pushed by expanders - if ((lastSwapColumn->fFlags & CLV_EXPANDER) != 0 - || (lastSwapColumn->fPushedByExpander - && ((lastSwapColumn->fFlags & CLV_PUSH_PASS) - != 0))) { - int32 columnCount - = fDisplayList->CountItems(); - for (int32 j = fDisplayList->IndexOf( - lastSwapColumn) + 1; - j < columnCount; j++) { - CLVColumn* column = - (CLVColumn*)fDisplayList->ItemAt(j); - if (column->IsShown()) { - if (column->fPushedByExpander) - MainViewUpdateRight - = column->fColumnEnd; - else - break; - } - } - } - fParent->Invalidate(BRect(MainViewUpdateLeft, - mainBounds.top, MainViewUpdateRight, - mainBounds.bottom)); - } - } while (hasColumnSnapped); - // erase and redraw the drag rectangle but not the - // interior to avoid label flicker - float min = fPreviousDragOutlineLeft; - float max = fPreviousDragOutlineRight; - float min2 = mousePosition.x - fDragBoxMouseHoldOffset; - float groupBegin = ((CLVDragGroup*)fDragGroupsList.ItemAt( - fDragGroupIndex))->groupBeginIndex; - if (min2 < groupBegin && fSnapGroupBeforeIndex == -1) - min2 = groupBegin; - - if (min2 > groupBegin && fSnapGroupAfterIndex == -1) - min2 = groupBegin; - - float max2 = min2 + fDragBoxWidth; - float Temp; - if (min2 < min || min == -1.0) { - Temp = min2; - min2 = min; - min = Temp; - } - - if (max2 > max || max == -1.0) { - Temp = max2; - max2 = max; - max = Temp; - } - Invalidate(BRect(min, bounds.top + 1.0, min, - bounds.bottom - 1.0)); - if (min2 != -1.0) { - Invalidate(BRect(min2, bounds.top + 1.0, min2, - bounds.bottom - 1.0)); - } - Invalidate(BRect(max, bounds.top + 1.0, max, - bounds.bottom - 1.0)); - if (max2 != -1.0) { - Invalidate(BRect(max2, bounds.top + 1.0, max2, - bounds.bottom - 1.0)); - } - Invalidate(BRect(min, bounds.top, max, bounds.top)); - Invalidate(BRect(min, bounds.bottom, max, - bounds.bottom)); - } - } - } else { - // user is resizing the column - if (mousePosition.x < fPreviousMousePosition.x - || mousePosition.x > fPreviousMousePosition.x) { - float newWidth = mousePosition.x - fResizeMouseHoldOffset - - fColumnClicked->fColumnBegin; - if (newWidth < fColumnClicked->fMinWidth) - newWidth = fColumnClicked->fMinWidth; - - if (newWidth != fColumnClicked->fWidth) { - fColumnClicked->SetWidth(newWidth); - fParent->ColumnWidthChanged(fParent->IndexOfColumn( - fColumnClicked), newWidth); - } - } - } - } else if (buttons == 0) { - // mouse button was released - if (!fColumnDragging && !fColumnResizing) { - // column was clicked - if ((columnFlags & CLV_SORT_KEYABLE) != 0) { - // column is a "sortable" column - if ((modifiers & B_SHIFT_KEY) == 0) { - // user wants to select it as the main sorting column - if (fParent->fSortKeyList.ItemAt(0) == fColumnClicked) { - // column was already selected; switch sort modes - fParent->ReverseSortMode( - fParent->fColumnList.IndexOf(fColumnClicked)); - } else { - //The user selected this column for sorting - fParent->SetSortKey( - fParent->fColumnList.IndexOf(fColumnClicked)); - } - } else { - // user wants to add it as a secondary sorting column - if (fParent->fSortKeyList.HasItem(fColumnClicked)) { - // column was already selected; switch sort modes - fParent->ReverseSortMode( - fParent->fColumnList.IndexOf(fColumnClicked)); - } else { - // user selected this column for sorting - fParent->AddSortKey( - fParent->fColumnList.IndexOf(fColumnClicked)); - } - } - } - } else if (fColumnDragging) { - // column was dragging; erase the drag box but not - // the interior to avoid label flicker - Invalidate(BRect(fPreviousDragOutlineLeft, bounds.top + 1.0, - fPreviousDragOutlineLeft, bounds.bottom - 1.0)); - Invalidate(BRect(fPreviousDragOutlineRight, bounds.top + 1.0, - fPreviousDragOutlineRight, bounds.bottom - 1.0)); - Invalidate(BRect(fPreviousDragOutlineLeft, bounds.top, - fPreviousDragOutlineRight, bounds.top)); - Invalidate(BRect(fPreviousDragOutlineLeft, bounds.bottom, - fPreviousDragOutlineRight, bounds.bottom)); - } else { - // column was resizing; erase the drag tab - Invalidate(BRect(fColumnClicked->fColumnEnd, - bounds.top, fColumnClicked->fColumnEnd, - bounds.bottom)); - } - - // unhighlight the label and forget the column - Invalidate(BRect(fColumnClicked->fColumnBegin + 1.0, - bounds.top + 1.0, fColumnClicked->fColumnEnd - 1.0, - bounds.bottom - 1.0)); - fColumnClicked = NULL; - fColumnDragging = false; - fColumnResizing = false; - } else { - // unused button combination, unhighlight the label and - // forget the column - Invalidate(BRect(fColumnClicked->fColumnBegin + 1.0, - bounds.top + 1.0, fColumnClicked->fColumnEnd - 1.0, - bounds.bottom - 1.0)); - fColumnClicked = NULL; - fColumnDragging = false; - fColumnResizing = false; - } - - fPreviousMousePosition = mousePosition; - } -} - - -// Shift the drag group into a new position -void -CLVColumnLabelView::ShiftDragGroup(int32 newPosition) -{ - int32 groupCount = fDragGroupsList.CountItems(); - CLVDragGroup* group; - BList newDisplayList; - - //Copy the groups up to the new position - for (int32 i = 0; i < newPosition; i++) { - if (i != fDragGroupIndex) { - group = (CLVDragGroup*)fDragGroupsList.ItemAt(i); - for (int32 j = group->groupStartDisplayListIndex; - j <= group->groupStopDisplayListIndex; j++) { - newDisplayList.AddItem(fDisplayList->ItemAt(j)); - } - } - } - - // copy the group into the new position - group = (CLVDragGroup*)fDragGroupsList.ItemAt(fDragGroupIndex); - for (int32 j = group->groupStartDisplayListIndex; - j <= group->groupStopDisplayListIndex; j++) { - newDisplayList.AddItem(fDisplayList->ItemAt(j)); - } - - // copy the rest of the groups, but skip the dragging group - for (int32 i = newPosition; i < groupCount; i++) { - if (i != fDragGroupIndex) { - group = (CLVDragGroup*)fDragGroupsList.ItemAt(i); - for (int32 j = group->groupStartDisplayListIndex; - j <= group->groupStopDisplayListIndex; j++) { - newDisplayList.AddItem(fDisplayList->ItemAt(j)); - } - } - } - - // set the new order - *fDisplayList = newDisplayList; - - // update columns and drag groups - fParent->ShiftDragGroup(); - UpdateDragGroups(); - SetSnapMinMax(); - - // inform the program that the display order changed - int32* newOrder = fParent->DisplayOrder(); - fParent->DisplayOrderChanged(newOrder); - delete[] newOrder; -} - - -// Make a copy of the DragGroups list, use it to store -// the CLVDragGroup's for recycling. -void -CLVColumnLabelView::UpdateDragGroups() -{ - BList tempList(fDragGroupsList); - fDragGroupsList.MakeEmpty(); - int32 columnCount = fDisplayList->CountItems(); - bool shouldContinueGroup = false; - CLVDragGroup* CurrentGroup = NULL; - - for (int32 i = 0; i < columnCount; i++) { - CLVColumn* CurrentColumn = (CLVColumn*)fDisplayList->ItemAt(i); - if (!shouldContinueGroup) { - // recycle or obtain a new CLVDragGroup - CurrentGroup = (CLVDragGroup*)tempList.RemoveItem(int32(0)); - if (CurrentGroup == NULL) - CurrentGroup = new CLVDragGroup; - - // add the CLVDragGroup to the DragGroups list - fDragGroupsList.AddItem(CurrentGroup); - // set up the new DragGroup - CurrentGroup->groupStartDisplayListIndex = i; - CurrentGroup->groupStopDisplayListIndex = i; - CurrentGroup->flags = 0; - - if (CurrentColumn->IsShown()) { - CurrentGroup->groupBeginIndex = CurrentColumn->fColumnBegin; - CurrentGroup->groupEndIndex = CurrentColumn->fColumnEnd; - CurrentGroup->lastColumnShown = CurrentColumn; - CurrentGroup->isShown = true; - if (CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING) - CurrentGroup->isAllLockBeginning = true; - else - CurrentGroup->isAllLockBeginning = false; - - if (CurrentColumn->fFlags & CLV_LOCK_AT_END) - CurrentGroup->isAllLockEnd = true; - else - CurrentGroup->isAllLockEnd = false; - } else { - CurrentGroup->groupBeginIndex = -1.0; - CurrentGroup->groupEndIndex = -1.0; - CurrentGroup->lastColumnShown = NULL; - CurrentGroup->isShown = false; - if (CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING) - CurrentGroup->isAllLockBeginning = true; - else - CurrentGroup->isAllLockBeginning = false; - if (CurrentColumn->fFlags & CLV_LOCK_AT_END) - CurrentGroup->isAllLockEnd = true; - else - CurrentGroup->isAllLockEnd = false; - } - } else { - // add this column to the current DragGroup - CurrentGroup->groupStopDisplayListIndex = i; - if (CurrentColumn->IsShown()) { - if (CurrentGroup->groupBeginIndex == -1.0) - CurrentGroup->groupBeginIndex = CurrentColumn->fColumnBegin; - CurrentGroup->groupEndIndex = CurrentColumn->fColumnEnd; - CurrentGroup->lastColumnShown = CurrentColumn; - CurrentGroup->isShown = true; - } - if ((CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING) == 0) - CurrentGroup->isAllLockBeginning = false; - if ((CurrentColumn->fFlags & CLV_LOCK_AT_END) == 0) - CurrentGroup->isAllLockEnd = false; - } - - CurrentGroup->flags = CurrentColumn->fFlags - & (CLV_NOT_MOVABLE | CLV_LOCK_AT_BEGINNING - | CLV_LOCK_AT_END); - // see if I should add more columns to this group - if (CurrentColumn->fFlags & CLV_LOCK_WITH_RIGHT) - shouldContinueGroup = true; - else - shouldContinueGroup = false; - } - // if any unused groups remain in tempList, delete them - while ((CurrentGroup = (CLVDragGroup*)tempList.RemoveItem(int32(0))) - != NULL) { - delete CurrentGroup; - } -} - - -// find the column group that the user is dragging and the shown -// group before it -void -CLVColumnLabelView::SetSnapMinMax() -{ - int32 groupCount = fDragGroupsList.CountItems(); - int32 columnCount; - fDragGroupIndex = -1; - fShownGroupBefore = NULL; - fSnapGroupBeforeIndex = -1; - CLVDragGroup* group; - for (int32 i = 0; i < groupCount; i++) { - group = (CLVDragGroup*)fDragGroupsList.ItemAt(i); - for (columnCount = group->groupStartDisplayListIndex; - columnCount <= group->groupStopDisplayListIndex; columnCount++) { - if (fDisplayList->ItemAt(columnCount) == fColumnClicked) { - fDragGroupIndex = i; - fDragGroup = group; - break; - } - } [ *** diff truncated: 3058 lines dropped *** ]