void ShortcutsWindow::MessageReceived(BMessage* msg) { switch(msg->what) { case OPEN_KEYSET: case APPEND_KEYSET: fLastOpenWasAppend = (msg->what == APPEND_KEYSET); if (fOpenPanel) fOpenPanel->Show(); else { BMessenger m(this); fOpenPanel = new BFilePanel(B_OPEN_PANEL, &m, NULL, 0, false); fOpenPanel->Show(); } fOpenPanel->SetButtonLabel(B_DEFAULT_BUTTON, fLastOpenWasAppend ? "Append" : "Open"); break; case REVERT_KEYSET: { // Send a message to myself, to get me to reload the settings file fLastOpenWasAppend = false; BMessage reload(B_REFS_RECEIVED); entry_ref eref; _GetSettingsFile(&eref); reload.AddRef("refs", &eref); reload.AddString("startupRef", "yeah"); PostMessage(&reload); } break; // Respond to drag-and-drop messages here case B_SIMPLE_DATA: { int i = 0; entry_ref ref; while (msg->FindRef("refs", i++, &ref) == B_NO_ERROR) { BEntry entry(&ref); if (entry.InitCheck() == B_NO_ERROR) { BPath path(&entry); if (path.InitCheck() == B_NO_ERROR) { // Add a new item with the given path. BString str(path.Path()); DoStandardEscapes(str); _AddNewSpec(str.String()); } } } } break; // Respond to FileRequester's messages here case B_REFS_RECEIVED: { // Find file ref entry_ref ref; bool isStartMsg = msg->HasString("startupRef"); if (msg->FindRef("refs", &ref) == B_NO_ERROR) { // load the file into (fileMsg) BMessage fileMsg; { BFile file(&ref, B_READ_ONLY); if ((file.InitCheck() != B_NO_ERROR) || (fileMsg.Unflatten(&file) != B_NO_ERROR)) { if (isStartMsg) { // use this to save to anyway fLastSaved = BEntry(&ref); break; } else { (new BAlert(ERROR, "Shortcuts was couldn't open your KeySet file!" , "Okay"))->Go(NULL); break; } } } if (fLastOpenWasAppend == false) { // Clear the menu... ShortcutsSpec * item; do { delete (item = ((ShortcutsSpec*) fColumnListView->RemoveItem(int32(0)))); } while (item); } if (_LoadKeySet(fileMsg)) { if (isStartMsg) fLastSaved = BEntry(&ref); fSaveButton->SetEnabled(isStartMsg == false); // If we just loaded in the Shortcuts settings file, then // no need to tell the user to save on exit. entry_ref eref; _GetSettingsFile(&eref); if (ref == eref) fKeySetModified = false; } else { (new BAlert(ERROR, "Shortcuts was unable to parse your KeySet file!", "Okay"))->Go(NULL); break; } } } break; // These messages come from the pop-up menu of the Applications column case SELECT_APPLICATION: { int csel = fColumnListView->CurrentSelection(); if (csel >= 0) { entry_ref aref; if (msg->FindRef("refs", &aref) == B_NO_ERROR) { BEntry ent(&aref); if (ent.InitCheck() == B_NO_ERROR) { BPath path; if ((ent.GetPath(&path) == B_NO_ERROR) && (((ShortcutsSpec *) fColumnListView->ItemAt(csel))-> ProcessColumnTextString(ShortcutsSpec:: STRING_COLUMN_INDEX, path.Path()))) { fColumnListView->InvalidateItem(csel); _MarkKeySetModified(); } } } } } break; case SAVE_KEYSET: { bool showSaveError = false; const char * name; entry_ref entry; if ((msg->FindString("name", &name) == B_NO_ERROR) && (msg->FindRef("directory", &entry) == B_NO_ERROR)) { BDirectory dir(&entry); BEntry saveTo(&dir, name, true); showSaveError = ((saveTo.InitCheck() != B_NO_ERROR) || (_SaveKeySet(saveTo) == false)); } else if (fLastSaved.InitCheck() == B_NO_ERROR) { // We've saved this before, save over previous file. showSaveError = (_SaveKeySet(fLastSaved) == false); } else PostMessage(SAVE_KEYSET_AS); // open the save requester... if (showSaveError) { (new BAlert(ERROR, "Shortcuts wasn't able to save your keyset." , "Okay"))->Go(NULL); } } break; case SAVE_KEYSET_AS: { if (fSavePanel) fSavePanel->Show(); else { BMessage msg(SAVE_KEYSET); BMessenger messenger(this); fSavePanel = new BFilePanel(B_SAVE_PANEL, &messenger, NULL, 0, false, &msg); fSavePanel->Show(); } } break; case B_ABOUT_REQUESTED: be_app_messenger.SendMessage(B_ABOUT_REQUESTED); break; case ADD_HOTKEY_ITEM: _AddNewSpec(NULL); break; case REMOVE_HOTKEY_ITEM: { int index = fColumnListView->CurrentSelection(); if (index >= 0) { CLVListItem* item = (CLVListItem*) fColumnListView->ItemAt(index); fColumnListView->RemoveItem(index); 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(); if (num > 0) { if (index < num) fColumnListView->Select(index); else { if (index > 0) index--; if (index < num) fColumnListView->Select(index); } } } } break; // Received when the user clicks on the ColumnListView case HOTKEY_ITEM_SELECTED: { int32 index = -1; msg->FindInt32("index", &index); bool validItem = (index >= 0); fRemoveButton->SetEnabled(validItem); } break; // Received when an entry is to be modified in response to GUI activity case HOTKEY_ITEM_MODIFIED: { int32 row, column; if ((msg->FindInt32("row", &row) == B_NO_ERROR) && (msg->FindInt32("column", &column) == B_NO_ERROR)) { int32 key; const char* bytes; if (row >= 0) { ShortcutsSpec* item = (ShortcutsSpec*) fColumnListView->ItemAt(row); bool repaintNeeded = false; // default if (msg->HasInt32("mouseClick")) { repaintNeeded = item->ProcessColumnMouseClick(column); } else if ((msg->FindString("bytes", &bytes) == B_NO_ERROR) && (msg->FindInt32("key", &key) == B_NO_ERROR)) { repaintNeeded = item->ProcessColumnKeyStroke(column, bytes, key); } else if (msg->FindInt32("unmappedkey", &key) == B_NO_ERROR) { repaintNeeded = ((column == item->KEY_COLUMN_INDEX) && ((key > 0xFF) || (GetKeyName(key) != NULL)) && (item->ProcessColumnKeyStroke(column, NULL, key))); } else if (msg->FindString("text", &bytes) == B_NO_ERROR) { if ((bytes[0] == '(')&&(bytes[1] == 'C')) { if (fSelectPanel) fSelectPanel->Show(); else { BMessage msg(SELECT_APPLICATION); BMessenger m(this); fSelectPanel = new BFilePanel(B_OPEN_PANEL, &m, NULL, 0, false, &msg); fSelectPanel->Show(); } fSelectPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); } else repaintNeeded = item->ProcessColumnTextString( column, bytes); } if (repaintNeeded) { fColumnListView->InvalidateItem(row); _MarkKeySetModified(); } } } } break; default: BWindow::MessageReceived(msg); break; } }
ShortcutsWindow::ShortcutsWindow() : BWindow(BRect(WINDOW_START_X, WINDOW_START_Y, WINDOW_START_X + MIN_WIDTH, WINDOW_START_Y + MIN_HEIGHT * 2), "Shortcuts", B_DOCUMENT_WINDOW, 0L), fSavePanel(NULL), fOpenPanel(NULL), fSelectPanel(NULL), fKeySetModified(false), fLastOpenWasAppend(false) { InitializeMetaMaps(); SetSizeLimits(MIN_WIDTH, MAX_WIDTH, MIN_HEIGHT, MAX_HEIGHT); BMenuBar* menuBar = new BMenuBar(BRect(0, 0, 0, 0), "Menu Bar"); BMenu* fileMenu = new BMenu("File"); fileMenu->AddItem(new BMenuItem("Open KeySet...", new BMessage(OPEN_KEYSET), 'O')); fileMenu->AddItem(new BMenuItem("Append KeySet...", new BMessage(APPEND_KEYSET), 'A')); fileMenu->AddItem(new BMenuItem("Revert to saved", new BMessage(REVERT_KEYSET), 'A')); fileMenu->AddItem(new BSeparatorItem); fileMenu->AddItem(new BMenuItem("Save KeySet as...", new BMessage(SAVE_KEYSET_AS), 'S')); fileMenu->AddItem(new BSeparatorItem); fileMenu->AddItem(new BMenuItem("About Shortcuts", new BMessage(B_ABOUT_REQUESTED))); fileMenu->AddItem(new BSeparatorItem); fileMenu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q')); menuBar->AddItem(fileMenu); AddChild(menuBar); font_height fh; be_plain_font->GetHeight(&fh); float vButtonHeight = ceil(fh.ascent) + ceil(fh.descent) + 5.0f; BRect tableBounds = Bounds(); tableBounds.top = menuBar->Bounds().bottom + 1; tableBounds.right -= B_V_SCROLL_BAR_WIDTH; tableBounds.bottom -= (B_H_SCROLL_BAR_HEIGHT + V_SPACING + vButtonHeight + V_SPACING * 2); 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)); const float metaWidth = 50.0f; for (int i = 0; i < ShortcutsSpec::NUM_META_COLUMNS; i++) fColumnListView->AddColumn( new CLVColumn(ShortcutsSpec::GetColumnName(i), CreateMetaPopUp(i), metaWidth, CLV_SORT_KEYABLE)); fColumnListView->AddColumn(new CLVColumn("Key", CreateKeysPopUp(), 60, CLV_SORT_KEYABLE)); BPopUpMenu* popup = new BPopUpMenu(NULL, false); popup->AddItem(new BMenuItem("(Choose application with file requester)", NULL)); popup->AddItem(new BMenuItem("*InsertString \"Your Text Here\"", NULL)); popup->AddItem(new BMenuItem("*MoveMouse +20 +0", NULL)); popup->AddItem(new BMenuItem("*MoveMouseTo 50% 50%", NULL)); popup->AddItem(new BMenuItem("*MouseButton 1", NULL)); popup->AddItem(new BMenuItem("*LaunchHandler text/html", NULL)); popup->AddItem(new BMenuItem( "*Multi \"*MoveMouseTo 100% 0\" \"*MouseButton 1\"", NULL)); popup->AddItem(new BMenuItem("*MouseDown", NULL)); popup->AddItem(new BMenuItem("*MouseUp", NULL)); popup->AddItem(new BMenuItem( "*SendMessage application/x-vnd.Be-TRAK 'Tfnd'", NULL)); popup->AddItem(new BMenuItem("*Beep", NULL)); fColumnListView->AddColumn(new CLVColumn("Application", popup, 323.0, CLV_SORT_KEYABLE)); fColumnListView->SetSortFunction(ShortcutsSpec::MyCompare); AddChild(containerView); fColumnListView->SetSelectionMessage(new BMessage(HOTKEY_ITEM_SELECTED)); fColumnListView->SetTarget(this); BRect buttonBounds = Bounds(); buttonBounds.left += V_SPACING; buttonBounds.right = ((buttonBounds.right - buttonBounds.left) / 2.0f) + buttonBounds.left; buttonBounds.bottom -= V_SPACING * 2; buttonBounds.top = buttonBounds.bottom - vButtonHeight; buttonBounds.right -= B_V_SCROLL_BAR_WIDTH; float origRight = buttonBounds.right; buttonBounds.right = (buttonBounds.left + origRight) * 0.40f - (V_SPACING / 2); AddChild(fAddButton = new ResizableButton(Bounds(), buttonBounds, "add", "Add new shortcut", new BMessage(ADD_HOTKEY_ITEM))); buttonBounds.left = buttonBounds.right + V_SPACING; buttonBounds.right = origRight; AddChild(fRemoveButton = new ResizableButton(Bounds(), buttonBounds, "remove", "Remove selected shortcut", new BMessage(REMOVE_HOTKEY_ITEM))); fRemoveButton->SetEnabled(false); float offset = (buttonBounds.right - buttonBounds.left) / 2.0f; BRect saveButtonBounds = buttonBounds; saveButtonBounds.right = Bounds().right - B_V_SCROLL_BAR_WIDTH - offset; saveButtonBounds.left = buttonBounds.right + V_SPACING + offset; AddChild(fSaveButton = new ResizableButton(Bounds(), saveButtonBounds, "save", "Save & apply", new BMessage(SAVE_KEYSET))); fSaveButton->SetEnabled(false); entry_ref ref; if (_GetSettingsFile(&ref)) { BMessage msg(B_REFS_RECEIVED); msg.AddRef("refs", &ref); msg.AddString("startupRef", "please"); PostMessage(&msg); // Tell ourself to load this file if it exists. } Show(); }
ShortcutsWindow::ShortcutsWindow() : BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_SYSTEM_NAME("Shortcuts"), B_TITLED_WINDOW, 0L), fSavePanel(NULL), fOpenPanel(NULL), fSelectPanel(NULL), fKeySetModified(false), fLastOpenWasAppend(false) { ShortcutsSpec::InitializeMetaMaps(); 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")); fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Open KeySet" B_UTF8_ELLIPSIS), new BMessage(OPEN_KEYSET), 'O')); fileMenu->AddItem(new BMenuItem( B_TRANSLATE("Append KeySet" B_UTF8_ELLIPSIS), new BMessage(APPEND_KEYSET), 'A')); fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Revert to saved"), new BMessage(REVERT_KEYSET), 'A')); fileMenu->AddItem(new BSeparatorItem); fileMenu->AddItem(new BMenuItem( B_TRANSLATE("Save KeySet as" B_UTF8_ELLIPSIS), new BMessage(SAVE_KEYSET_AS), 'S')); fileMenu->AddItem(new BSeparatorItem); fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Quit"), 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)); 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". for (int i = 0; i < ShortcutsSpec::NUM_META_COLUMNS; i++) { 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)); } float keyCellWidth = be_plain_font->StringWidth("Caps Lock") + 20; fColumnListView->AddColumn(new CLVColumn(B_TRANSLATE("Key"), CreateKeysPopUp(), keyCellWidth, CLV_SORT_KEYABLE)); minListWidth += keyCellWidth + 1; BPopUpMenu* popup = new BPopUpMenu(NULL, false); popup->AddItem(new BMenuItem( B_TRANSLATE("(Choose application with file requester)"), NULL)); popup->AddItem(new BMenuItem( B_TRANSLATE("*InsertString \"Your Text Here\""), NULL)); popup->AddItem(new BMenuItem( B_TRANSLATE("*MoveMouse +20 +0"), NULL)); popup->AddItem(new BMenuItem(B_TRANSLATE("*MoveMouseTo 50% 50%"), NULL)); popup->AddItem(new BMenuItem(B_TRANSLATE("*MouseButton 1"), NULL)); popup->AddItem(new BMenuItem( B_TRANSLATE("*LaunchHandler text/html"), NULL)); popup->AddItem(new BMenuItem( B_TRANSLATE("*Multi \"*MoveMouseTo 100% 0\" \"*MouseButton 1\""), NULL)); popup->AddItem(new BMenuItem(B_TRANSLATE("*MouseDown"), NULL)); popup->AddItem(new BMenuItem(B_TRANSLATE("*MouseUp"), NULL)); 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::MyCompare); top->AddChild(containerView); fColumnListView->SetSelectionMessage(new BMessage(HOTKEY_ITEM_SELECTED)); fColumnListView->SetTarget(this); fAddButton = new BButton(BRect(0, 0, 0, 0), "add", B_TRANSLATE("Add new shortcut"), new BMessage(ADD_HOTKEY_ITEM), B_FOLLOW_BOTTOM); 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"), new BMessage(REMOVE_HOTKEY_ITEM), B_FOLLOW_BOTTOM); fRemoveButton->ResizeToPreferred(); fRemoveButton->MoveBy(fAddButton->Frame().right + spacing, Bounds().bottom - fRemoveButton->Bounds().bottom - spacing); top->AddChild(fRemoveButton); fRemoveButton->SetEnabled(false); fSaveButton = new BButton(BRect(0, 0, 0, 0), "save", B_TRANSLATE("Save & apply"), new BMessage(SAVE_KEYSET), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT); 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; if (_GetWindowSettingsFile(&windowSettingsRef)) { // The window settings file is not accepted via B_REFS_RECEIVED; this // is a behind-the-scenes file that the user will never see or // interact with. BFile windowSettingsFile(&windowSettingsRef, B_READ_ONLY); BMessage loadMsg; if (loadMsg.Unflatten(&windowSettingsFile) == B_OK) _LoadWindowSettings(loadMsg); } entry_ref keySetRef; if (_GetSettingsFile(&keySetRef)) { BMessage msg(B_REFS_RECEIVED); msg.AddRef("refs", &keySetRef); msg.AddString("startupRef", "please"); PostMessage(&msg); // Tell ourselves to load this file if it exists. } Show(); }