ShortcutsWindow.cpp revision 546208a5
16c333678SFredrik Modeen/*
23672a07eSStephan Aßmus * Copyright 1999-2010 Haiku Inc. All rights reserved.
36c333678SFredrik Modeen * Distributed under the terms of the MIT License.
46c333678SFredrik Modeen *
56c333678SFredrik Modeen * Authors:
66c333678SFredrik Modeen *		Jeremy Friesner
76c333678SFredrik Modeen *		Fredrik Mod��en
86c333678SFredrik Modeen */
96c333678SFredrik Modeen
106c333678SFredrik Modeen
11fa1ee6d4SJonas Sundström#include "ShortcutsWindow.h"
126c333678SFredrik Modeen
136c333678SFredrik Modeen#include <math.h>
146c333678SFredrik Modeen#include <stdio.h>
156c333678SFredrik Modeen
166c333678SFredrik Modeen#include <Alert.h>
176c333678SFredrik Modeen#include <Application.h>
18ce59b51cSRene Gollent#include <Button.h>
193672a07eSStephan Aßmus#include <Catalog.h>
206c333678SFredrik Modeen#include <Clipboard.h>
21ce59b51cSRene Gollent#include <ControlLook.h>
22fa1ee6d4SJonas Sundström#include <File.h>
23ce59b51cSRene Gollent#include <FilePanel.h>
24fa1ee6d4SJonas Sundström#include <FindDirectory.h>
25fa1ee6d4SJonas Sundström#include <Input.h>
263672a07eSStephan Aßmus#include <Locale.h>
27ce59b51cSRene Gollent#include <Message.h>
286c333678SFredrik Modeen#include <Menu.h>
296c333678SFredrik Modeen#include <MenuBar.h>
30fa1ee6d4SJonas Sundström#include <MenuItem.h>
31fa1ee6d4SJonas Sundström#include <MessageFilter.h>
32fa1ee6d4SJonas Sundström#include <Path.h>
33fa1ee6d4SJonas Sundström#include <PopUpMenu.h>
34ce59b51cSRene Gollent#include <Screen.h>
356c333678SFredrik Modeen#include <ScrollBar.h>
366c333678SFredrik Modeen#include <ScrollView.h>
376c333678SFredrik Modeen#include <String.h>
38ce59b51cSRene Gollent#include <SupportDefs.h>
396c333678SFredrik Modeen
406c333678SFredrik Modeen#include "ColumnListView.h"
416c333678SFredrik Modeen
426c333678SFredrik Modeen#include "KeyInfos.h"
436c333678SFredrik Modeen#include "MetaKeyStateMap.h"
44fa1ee6d4SJonas Sundström#include "ParseCommandLine.h"
456c333678SFredrik Modeen#include "ShortcutsFilterConstants.h"
46fa1ee6d4SJonas Sundström#include "ShortcutsSpec.h"
47fa1ee6d4SJonas Sundström
486c333678SFredrik Modeen
496c333678SFredrik Modeen// Window sizing constraints
50ce59b51cSRene Gollent#define MAX_WIDTH 10000
51ce59b51cSRene Gollent#define MAX_HEIGHT 10000
52ce59b51cSRene Gollent	// SetSizeLimits does not provide a mechanism for specifying an
53ce59b51cSRene Gollent	// unrestricted maximum.  10,000 seems to be the most common value used
54ce59b51cSRene Gollent	// in other Haiku system applications.
55ce59b51cSRene Gollent
56ce59b51cSRene Gollent#define WINDOW_SETTINGS_FILE_NAME "Shortcuts_window_settings"
57ce59b51cSRene Gollent	// Because the "shortcuts_settings" file (SHORTCUTS_SETTING_FILE_NAME) is
58ce59b51cSRene Gollent	// already used as a communications method between this configurator and
59ce59b51cSRene Gollent	// the "shortcut_catcher" input_server filter, it should not be overloaded
60ce59b51cSRene Gollent	// with window position information.  Instead, a separate file is used.
616c333678SFredrik Modeen
62546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
63546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "ShortcutsWindow"
643672a07eSStephan Aßmus
659c1a9b92SAdrien Destugues#define ERROR "Shortcuts error"
666c333678SFredrik Modeen#define WARNING "Shortcuts warning"
676c333678SFredrik Modeen
686c333678SFredrik Modeen
696c333678SFredrik Modeen// Creates a pop-up-menu that reflects the possible states of the specified
706c333678SFredrik Modeen// meta-key.
713672a07eSStephan Aßmusstatic BPopUpMenu*
723672a07eSStephan AßmusCreateMetaPopUp(int col)
736c333678SFredrik Modeen{
746c333678SFredrik Modeen	MetaKeyStateMap& map = GetNthKeyMap(col);
756c333678SFredrik Modeen	BPopUpMenu * popup = new BPopUpMenu(NULL, false);
766c333678SFredrik Modeen	int numStates = map.GetNumStates();
776c333678SFredrik Modeen
786c333678SFredrik Modeen	for (int i = 0; i < numStates; i++)
796c333678SFredrik Modeen		popup->AddItem(new BMenuItem(map.GetNthStateDesc(i), NULL));
806c333678SFredrik Modeen
816c333678SFredrik Modeen	return popup;
826c333678SFredrik Modeen}
836c333678SFredrik Modeen
84fa1ee6d4SJonas Sundström
856c333678SFredrik Modeen// Creates a pop-up that allows the user to choose a key-cap visually
863672a07eSStephan Aßmusstatic BPopUpMenu*
873672a07eSStephan AßmusCreateKeysPopUp()
886c333678SFredrik Modeen{
896c333678SFredrik Modeen	BPopUpMenu* popup = new BPopUpMenu(NULL, false);
906c333678SFredrik Modeen	int numKeys = GetNumKeyIndices();
916c333678SFredrik Modeen	for (int i = 0; i < numKeys; i++) {
926c333678SFredrik Modeen		const char* next = GetKeyName(i);
936c333678SFredrik Modeen
946c333678SFredrik Modeen		if (next)
956c333678SFredrik Modeen			popup->AddItem(new BMenuItem(next, NULL));
966c333678SFredrik Modeen	}
976c333678SFredrik Modeen	return popup;
986c333678SFredrik Modeen}
996c333678SFredrik Modeen
1006c333678SFredrik Modeen
1016c333678SFredrik ModeenShortcutsWindow::ShortcutsWindow()
1026c333678SFredrik Modeen	:
103ce59b51cSRene Gollent	BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_SYSTEM_NAME("Shortcuts"),
104ce59b51cSRene Gollent		B_TITLED_WINDOW, 0L),
1053672a07eSStephan Aßmus	fSavePanel(NULL),
1063672a07eSStephan Aßmus	fOpenPanel(NULL),
1073672a07eSStephan Aßmus	fSelectPanel(NULL),
1083672a07eSStephan Aßmus	fKeySetModified(false),
1093672a07eSStephan Aßmus	fLastOpenWasAppend(false)
1106c333678SFredrik Modeen{
1113672a07eSStephan Aßmus	ShortcutsSpec::InitializeMetaMaps();
112ce59b51cSRene Gollent
113ce59b51cSRene Gollent	float spacing = be_control_look->DefaultItemSpacing();
114ce59b51cSRene Gollent
115ce59b51cSRene Gollent	BView* top = new BView(Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0);
116ce59b51cSRene Gollent	top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
117ce59b51cSRene Gollent	AddChild(top);
1183672a07eSStephan Aßmus
1196c333678SFredrik Modeen	BMenuBar* menuBar = new BMenuBar(BRect(0, 0, 0, 0), "Menu Bar");
1206c333678SFredrik Modeen
1213672a07eSStephan Aßmus	BMenu* fileMenu = new BMenu(B_TRANSLATE("File"));
122ce59b51cSRene Gollent	fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Open KeySet" B_UTF8_ELLIPSIS),
1236c333678SFredrik Modeen		new BMessage(OPEN_KEYSET), 'O'));
1243672a07eSStephan Aßmus	fileMenu->AddItem(new BMenuItem(
125ce59b51cSRene Gollent		B_TRANSLATE("Append KeySet" B_UTF8_ELLIPSIS),
1266c333678SFredrik Modeen		new BMessage(APPEND_KEYSET), 'A'));
127ce59b51cSRene Gollent	fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Revert to saved"),
1286c333678SFredrik Modeen		new BMessage(REVERT_KEYSET), 'A'));
1296c333678SFredrik Modeen	fileMenu->AddItem(new BSeparatorItem);
1303672a07eSStephan Aßmus	fileMenu->AddItem(new BMenuItem(
131ce59b51cSRene Gollent		B_TRANSLATE("Save KeySet as" B_UTF8_ELLIPSIS),
1326c333678SFredrik Modeen		new BMessage(SAVE_KEYSET_AS), 'S'));
1336c333678SFredrik Modeen	fileMenu->AddItem(new BSeparatorItem);
1343672a07eSStephan Aßmus	fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
1353672a07eSStephan Aßmus		new BMessage(B_QUIT_REQUESTED), 'Q'));
1366c333678SFredrik Modeen	menuBar->AddItem(fileMenu);
1376c333678SFredrik Modeen
138ce59b51cSRene Gollent	top->AddChild(menuBar);
1396c333678SFredrik Modeen
1406c333678SFredrik Modeen	BRect tableBounds = Bounds();
1416c333678SFredrik Modeen	tableBounds.top = menuBar->Bounds().bottom + 1;
1426c333678SFredrik Modeen	tableBounds.right -= B_V_SCROLL_BAR_WIDTH;
143ce59b51cSRene Gollent	tableBounds.bottom -= B_H_SCROLL_BAR_HEIGHT;
144ce59b51cSRene Gollent
1456c333678SFredrik Modeen	BScrollView* containerView;
146ce59b51cSRene Gollent	fColumnListView = new ColumnListView(tableBounds, &containerView, NULL,
147ce59b51cSRene Gollent		B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
1486c333678SFredrik Modeen		B_SINGLE_SELECTION_LIST, true, true, true, B_NO_BORDER);
149ce59b51cSRene Gollent
150ce59b51cSRene Gollent	fColumnListView->SetEditMessage(new BMessage(HOTKEY_ITEM_MODIFIED),
1516c333678SFredrik Modeen		BMessenger(this));
152ce59b51cSRene Gollent
153ce59b51cSRene Gollent	float minListWidth = 0;
154ce59b51cSRene Gollent		// A running total is kept as the columns are created.
155ce59b51cSRene Gollent	float cellWidth = be_plain_font->StringWidth("Either") + 20;
156ce59b51cSRene Gollent		// ShortcutsSpec does not seem to translate the string "Either".
1576c333678SFredrik Modeen
1583672a07eSStephan Aßmus	for (int i = 0; i < ShortcutsSpec::NUM_META_COLUMNS; i++) {
159ce59b51cSRene Gollent		const char* name = ShortcutsSpec::GetColumnName(i);
160ce59b51cSRene Gollent		float headerWidth = be_plain_font->StringWidth(name) + 20;
161ce59b51cSRene Gollent		float width = max_c(headerWidth, cellWidth);
162ce59b51cSRene Gollent		minListWidth += width + 1;
163ce59b51cSRene Gollent
1646c333678SFredrik Modeen		fColumnListView->AddColumn(
165ce59b51cSRene Gollent			new CLVColumn(name, CreateMetaPopUp(i), width, CLV_SORT_KEYABLE));
1663672a07eSStephan Aßmus	}
1676c333678SFredrik Modeen
168ce59b51cSRene Gollent	float keyCellWidth = be_plain_font->StringWidth("Caps Lock") + 20;
1693672a07eSStephan Aßmus	fColumnListView->AddColumn(new CLVColumn(B_TRANSLATE("Key"),
170ce59b51cSRene Gollent		CreateKeysPopUp(), keyCellWidth, CLV_SORT_KEYABLE));
171ce59b51cSRene Gollent	minListWidth += keyCellWidth + 1;
1726c333678SFredrik Modeen
1736c333678SFredrik Modeen	BPopUpMenu* popup = new BPopUpMenu(NULL, false);
1746c333678SFredrik Modeen	popup->AddItem(new BMenuItem(
1753672a07eSStephan Aßmus		B_TRANSLATE("(Choose application with file requester)"), NULL));
1763672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(
1773672a07eSStephan Aßmus		B_TRANSLATE("*InsertString \"Your Text Here\""), NULL));
1786c333678SFredrik Modeen	popup->AddItem(new BMenuItem(
1793672a07eSStephan Aßmus		B_TRANSLATE("*MoveMouse +20 +0"), NULL));
1803672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(B_TRANSLATE("*MoveMouseTo 50% 50%"), NULL));
1813672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(B_TRANSLATE("*MouseButton 1"), NULL));
1823672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(
1833672a07eSStephan Aßmus		B_TRANSLATE("*LaunchHandler text/html"), NULL));
1843672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(
1853672a07eSStephan Aßmus		B_TRANSLATE("*Multi \"*MoveMouseTo 100% 0\" \"*MouseButton 1\""),
1863672a07eSStephan Aßmus		NULL));
1873672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(B_TRANSLATE("*MouseDown"), NULL));
1883672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(B_TRANSLATE("*MouseUp"), NULL));
1893672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(
1903672a07eSStephan Aßmus		B_TRANSLATE("*SendMessage application/x-vnd.Be-TRAK 'Tfnd'"), NULL));
1913672a07eSStephan Aßmus	popup->AddItem(new BMenuItem(B_TRANSLATE("*Beep"), NULL));
1923672a07eSStephan Aßmus	fColumnListView->AddColumn(new CLVColumn(B_TRANSLATE("Application"), popup,
1933672a07eSStephan Aßmus		323.0, CLV_SORT_KEYABLE));
194ce59b51cSRene Gollent	minListWidth += 323.0 + 1;
195ce59b51cSRene Gollent	minListWidth += B_V_SCROLL_BAR_WIDTH;
1966c333678SFredrik Modeen
1976c333678SFredrik Modeen	fColumnListView->SetSortFunction(ShortcutsSpec::MyCompare);
198ce59b51cSRene Gollent	top->AddChild(containerView);
1996c333678SFredrik Modeen
2006c333678SFredrik Modeen	fColumnListView->SetSelectionMessage(new BMessage(HOTKEY_ITEM_SELECTED));
2016c333678SFredrik Modeen	fColumnListView->SetTarget(this);
2026c333678SFredrik Modeen
203ce59b51cSRene Gollent	fAddButton = new BButton(BRect(0, 0, 0, 0), "add",
204ce59b51cSRene Gollent		B_TRANSLATE("Add new shortcut"), new BMessage(ADD_HOTKEY_ITEM),
205ce59b51cSRene Gollent		B_FOLLOW_BOTTOM);
206ce59b51cSRene Gollent	fAddButton->ResizeToPreferred();
207ce59b51cSRene Gollent	fAddButton->MoveBy(spacing,
208ce59b51cSRene Gollent		Bounds().bottom - fAddButton->Bounds().bottom - spacing);
209ce59b51cSRene Gollent	top->AddChild(fAddButton);
210ce59b51cSRene Gollent
211ce59b51cSRene Gollent	fRemoveButton = new BButton(BRect(0, 0, 0, 0), "remove",
212ce59b51cSRene Gollent		B_TRANSLATE("Remove selected shortcut"),
213ce59b51cSRene Gollent		new BMessage(REMOVE_HOTKEY_ITEM), B_FOLLOW_BOTTOM);
214ce59b51cSRene Gollent	fRemoveButton->ResizeToPreferred();
215ce59b51cSRene Gollent	fRemoveButton->MoveBy(fAddButton->Frame().right + spacing,
216ce59b51cSRene Gollent		Bounds().bottom - fRemoveButton->Bounds().bottom - spacing);
217ce59b51cSRene Gollent	top->AddChild(fRemoveButton);
218ce59b51cSRene Gollent
2196c333678SFredrik Modeen	fRemoveButton->SetEnabled(false);
2206c333678SFredrik Modeen
221ce59b51cSRene Gollent	fSaveButton = new BButton(BRect(0, 0, 0, 0), "save",
222ce59b51cSRene Gollent		B_TRANSLATE("Save & apply"), new BMessage(SAVE_KEYSET),
223ce59b51cSRene Gollent		B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT);
224ce59b51cSRene Gollent	fSaveButton->ResizeToPreferred();
225ce59b51cSRene Gollent	fSaveButton->MoveBy(Bounds().right - fSaveButton->Bounds().right - spacing,
226ce59b51cSRene Gollent		Bounds().bottom - fSaveButton->Bounds().bottom - spacing);
227ce59b51cSRene Gollent	top->AddChild(fSaveButton);
228ce59b51cSRene Gollent
2296c333678SFredrik Modeen	fSaveButton->SetEnabled(false);
2306c333678SFredrik Modeen
231ce59b51cSRene Gollent	containerView->ResizeBy(0,
232ce59b51cSRene Gollent		-(fAddButton->Bounds().bottom + 2 * spacing + 2));
233ce59b51cSRene Gollent
234ce59b51cSRene Gollent	float minButtonBarWidth = fRemoveButton->Frame().right
235ce59b51cSRene Gollent		+ fSaveButton->Bounds().right + 2 * spacing;
236ce59b51cSRene Gollent	float minWidth = max_c(minListWidth, minButtonBarWidth);
237ce59b51cSRene Gollent
238ce59b51cSRene Gollent	float menuBarHeight = menuBar->Bounds().bottom;
239ce59b51cSRene Gollent	float buttonBarHeight = Bounds().bottom - containerView->Frame().bottom;
240ce59b51cSRene Gollent	float minHeight = menuBarHeight + 200 + buttonBarHeight;
241ce59b51cSRene Gollent
242ce59b51cSRene Gollent	SetSizeLimits(minWidth, MAX_WIDTH, minHeight, MAX_HEIGHT);
243ce59b51cSRene Gollent		// SetSizeLimits() will resize the window to the minimum size.
244ce59b51cSRene Gollent
245ce59b51cSRene Gollent	CenterOnScreen();
246ce59b51cSRene Gollent
247ce59b51cSRene Gollent	entry_ref windowSettingsRef;
248ce59b51cSRene Gollent	if (_GetWindowSettingsFile(&windowSettingsRef)) {
249ce59b51cSRene Gollent		// The window settings file is not accepted via B_REFS_RECEIVED; this
250ce59b51cSRene Gollent		// is a behind-the-scenes file that the user will never see or
251ce59b51cSRene Gollent		// interact with.
252ce59b51cSRene Gollent		BFile windowSettingsFile(&windowSettingsRef, B_READ_ONLY);
253ce59b51cSRene Gollent		BMessage loadMsg;
254ce59b51cSRene Gollent		if (loadMsg.Unflatten(&windowSettingsFile) == B_OK)
255ce59b51cSRene Gollent			_LoadWindowSettings(loadMsg);
256ce59b51cSRene Gollent	}
257ce59b51cSRene Gollent
258ce59b51cSRene Gollent	entry_ref keySetRef;
259ce59b51cSRene Gollent	if (_GetSettingsFile(&keySetRef)) {
2606c333678SFredrik Modeen		BMessage msg(B_REFS_RECEIVED);
261ce59b51cSRene Gollent		msg.AddRef("refs", &keySetRef);
2626c333678SFredrik Modeen		msg.AddString("startupRef", "please");
263ce59b51cSRene Gollent		PostMessage(&msg);
264ce59b51cSRene Gollent			// Tell ourselves to load this file if it exists.
2656c333678SFredrik Modeen	}
2666c333678SFredrik Modeen	Show();
2676c333678SFredrik Modeen}
2686c333678SFredrik Modeen
2696c333678SFredrik Modeen
2706c333678SFredrik ModeenShortcutsWindow::~ShortcutsWindow()
2716c333678SFredrik Modeen{
2726c333678SFredrik Modeen	delete fSavePanel;
2736c333678SFredrik Modeen	delete fOpenPanel;
2746c333678SFredrik Modeen	delete fSelectPanel;
2756c333678SFredrik Modeen	be_app->PostMessage(B_QUIT_REQUESTED);
2766c333678SFredrik Modeen}
2776c333678SFredrik Modeen
2786c333678SFredrik Modeen
2796c333678SFredrik Modeenbool
2806c333678SFredrik ModeenShortcutsWindow::QuitRequested()
2816c333678SFredrik Modeen{
2826c333678SFredrik Modeen	bool ret = true;
2836c333678SFredrik Modeen
2846c333678SFredrik Modeen	if (fKeySetModified) {
2856c333678SFredrik Modeen		BAlert* alert = new BAlert(WARNING,
2863672a07eSStephan Aßmus			B_TRANSLATE("Really quit without saving your changes?"),
2873672a07eSStephan Aßmus			B_TRANSLATE("Don't save"), B_TRANSLATE("Cancel"),
2883672a07eSStephan Aßmus			B_TRANSLATE("Save"));
2896c333678SFredrik Modeen		switch(alert->Go()) {
2906c333678SFredrik Modeen			case 1:
2916c333678SFredrik Modeen				ret = false;
2923672a07eSStephan Aßmus				break;
2936c333678SFredrik Modeen
2946c333678SFredrik Modeen			case 2:
2956c333678SFredrik Modeen				// Save: automatically if possible, otherwise go back and open
2966c333678SFredrik Modeen				// up the file requester
2973672a07eSStephan Aßmus				if (fLastSaved.InitCheck() == B_OK) {
2986c333678SFredrik Modeen					if (_SaveKeySet(fLastSaved) == false) {
2996c333678SFredrik Modeen						(new BAlert(ERROR,
3003672a07eSStephan Aßmus							B_TRANSLATE("Shortcuts was unable to save your "
3013672a07eSStephan Aßmus								"KeySet file!"),
3023672a07eSStephan Aßmus							B_TRANSLATE("Oh no")))->Go();
3036c333678SFredrik Modeen						ret = true; //quit anyway
3046c333678SFredrik Modeen					}
3056c333678SFredrik Modeen				} else {
3066c333678SFredrik Modeen					PostMessage(SAVE_KEYSET);
3076c333678SFredrik Modeen					ret = false;
3086c333678SFredrik Modeen				}
3093672a07eSStephan Aßmus				break;
3106c333678SFredrik Modeen			default:
3116c333678SFredrik Modeen				ret = true;
3123672a07eSStephan Aßmus				break;
3136c333678SFredrik Modeen		}
3146c333678SFredrik Modeen	}
3156c333678SFredrik Modeen
316ce59b51cSRene Gollent	if (ret) {
317fa1ee6d4SJonas Sundström		fColumnListView->DeselectAll();
318ce59b51cSRene Gollent
319ce59b51cSRene Gollent		// Save the window position.
320ce59b51cSRene Gollent		entry_ref ref;
321ce59b51cSRene Gollent		if (_GetWindowSettingsFile(&ref)) {
322ce59b51cSRene Gollent			BEntry entry(&ref);
323ce59b51cSRene Gollent			_SaveWindowSettings(entry);
324ce59b51cSRene Gollent		}
325ce59b51cSRene Gollent	}
326ce59b51cSRene Gollent
3276c333678SFredrik Modeen	return ret;
3286c333678SFredrik Modeen}
3296c333678SFredrik Modeen
3306c333678SFredrik Modeen
3316c333678SFredrik Modeenbool
3326c333678SFredrik ModeenShortcutsWindow::_GetSettingsFile(entry_ref* eref)
3336c333678SFredrik Modeen{
3346c333678SFredrik Modeen	BPath path;
3356c333678SFredrik Modeen	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
3366c333678SFredrik Modeen		return false;
3376c333678SFredrik Modeen	else
3386c333678SFredrik Modeen		path.Append(SHORTCUTS_SETTING_FILE_NAME);
3396c333678SFredrik Modeen
3403672a07eSStephan Aßmus	if (BEntry(path.Path(), true).GetRef(eref) == B_OK)
3416c333678SFredrik Modeen		return true;
3426c333678SFredrik Modeen	else
3436c333678SFredrik Modeen		return false;
3446c333678SFredrik Modeen}
3456c333678SFredrik Modeen
3466c333678SFredrik Modeen
3476c333678SFredrik Modeen// Saves a settings file to (saveEntry). Returns true iff successful.
3486c333678SFredrik Modeenbool
3496c333678SFredrik ModeenShortcutsWindow::_SaveKeySet(BEntry& saveEntry)
3506c333678SFredrik Modeen{
3516c333678SFredrik Modeen	BFile saveTo(&saveEntry, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
3523672a07eSStephan Aßmus	if (saveTo.InitCheck() != B_OK)
3536c333678SFredrik Modeen		return false;
3546c333678SFredrik Modeen
3556c333678SFredrik Modeen	BMessage saveMsg;
3566c333678SFredrik Modeen	for (int i = 0; i < fColumnListView->CountItems(); i++) {
3576c333678SFredrik Modeen		BMessage next;
3586c333678SFredrik Modeen		if (((ShortcutsSpec*)fColumnListView->ItemAt(i))->Archive(&next)
3593672a07eSStephan Aßmus			== B_OK)
3606c333678SFredrik Modeen			saveMsg.AddMessage("spec", &next);
3616c333678SFredrik Modeen		else
3623672a07eSStephan Aßmus			printf("Error archiving ShortcutsSpec #%i!\n", i);
3636c333678SFredrik Modeen	}
3646c333678SFredrik Modeen
3653672a07eSStephan Aßmus	bool ret = (saveMsg.Flatten(&saveTo) == B_OK);
3666c333678SFredrik Modeen
3676c333678SFredrik Modeen	if (ret) {
3686c333678SFredrik Modeen		fKeySetModified = false;
3696c333678SFredrik Modeen		fSaveButton->SetEnabled(false);
3706c333678SFredrik Modeen	}
3716c333678SFredrik Modeen
3726c333678SFredrik Modeen	return ret;
3736c333678SFredrik Modeen}
3746c333678SFredrik Modeen
3756c333678SFredrik Modeen
3766c333678SFredrik Modeen// Appends new entries from the file specified in the "spec" entry of
3776c333678SFredrik Modeen// (loadMsg). Returns true iff successful.
3786c333678SFredrik Modeenbool
3796c333678SFredrik ModeenShortcutsWindow::_LoadKeySet(const BMessage& loadMsg)
3806c333678SFredrik Modeen{
3816c333678SFredrik Modeen	int i = 0;
3826c333678SFredrik Modeen	BMessage msg;
3833672a07eSStephan Aßmus	while (loadMsg.FindMessage("spec", i++, &msg) == B_OK) {
3846c333678SFredrik Modeen		ShortcutsSpec* spec = (ShortcutsSpec*)ShortcutsSpec::Instantiate(&msg);
3856c333678SFredrik Modeen		if (spec != NULL)
3866c333678SFredrik Modeen			fColumnListView->AddItem(spec);
3876c333678SFredrik Modeen		else
3886c333678SFredrik Modeen			printf("_LoadKeySet: Error parsing spec!\n");
3896c333678SFredrik Modeen	}
3906c333678SFredrik Modeen	return true;
3916c333678SFredrik Modeen}
3926c333678SFredrik Modeen
3936c333678SFredrik Modeen
394ce59b51cSRene Gollent// Gets the filesystem location of the "Shortcuts_window_settings" file.
395ce59b51cSRene Gollentbool
396ce59b51cSRene GollentShortcutsWindow::_GetWindowSettingsFile(entry_ref* eref)
397ce59b51cSRene Gollent{
398ce59b51cSRene Gollent	BPath path;
399ce59b51cSRene Gollent	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
400ce59b51cSRene Gollent		return false;
401ce59b51cSRene Gollent	else
402ce59b51cSRene Gollent		path.Append(WINDOW_SETTINGS_FILE_NAME);
403ce59b51cSRene Gollent
404ce59b51cSRene Gollent	return BEntry(path.Path(), true).GetRef(eref) == B_OK;
405ce59b51cSRene Gollent}
406ce59b51cSRene Gollent
407ce59b51cSRene Gollent
408ce59b51cSRene Gollent// Saves the application settings file to (saveEntry).  Because this is a
409ce59b51cSRene Gollent// non-essential file, errors are ignored when writing the settings.
410ce59b51cSRene Gollentvoid
411ce59b51cSRene GollentShortcutsWindow::_SaveWindowSettings(BEntry& saveEntry)
412ce59b51cSRene Gollent{
413ce59b51cSRene Gollent	BFile saveTo(&saveEntry, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
414ce59b51cSRene Gollent	if (saveTo.InitCheck() != B_OK)
415ce59b51cSRene Gollent		return;
416ce59b51cSRene Gollent
417ce59b51cSRene Gollent	BMessage saveMsg;
418ce59b51cSRene Gollent	saveMsg.AddRect("window frame", Frame());
419ce59b51cSRene Gollent
420ce59b51cSRene Gollent	for (int i = 0; i < fColumnListView->CountColumns(); i++) {
421ce59b51cSRene Gollent		CLVColumn* column = fColumnListView->ColumnAt(i);
422ce59b51cSRene Gollent		saveMsg.AddFloat("column width", column->Width());
423ce59b51cSRene Gollent	}
424ce59b51cSRene Gollent
425ce59b51cSRene Gollent	saveMsg.Flatten(&saveTo);
426ce59b51cSRene Gollent}
427ce59b51cSRene Gollent
428ce59b51cSRene Gollent
429ce59b51cSRene Gollent// Loads the application settings file from (loadMsg) and resizes the interface
430ce59b51cSRene Gollent// to match the previously saved settings.  Because this is a non-essential
431ce59b51cSRene Gollent// file, errors are ignored when loading the settings.
432ce59b51cSRene Gollentvoid
433ce59b51cSRene GollentShortcutsWindow::_LoadWindowSettings(const BMessage& loadMsg)
434ce59b51cSRene Gollent{
435ce59b51cSRene Gollent	BRect frame;
436ce59b51cSRene Gollent	if (loadMsg.FindRect("window frame", &frame) == B_OK) {
437ce59b51cSRene Gollent		// Ensure the frame does not resize below the computed minimum.
438ce59b51cSRene Gollent		float width = max_c(Bounds().right, frame.right - frame.left);
439ce59b51cSRene Gollent		float height = max_c(Bounds().bottom, frame.bottom - frame.top);
440ce59b51cSRene Gollent		ResizeTo(width, height);
441ce59b51cSRene Gollent
442ce59b51cSRene Gollent		// Ensure the frame is not placed outside of the screen.
443ce59b51cSRene Gollent		BScreen screen(this);
444ce59b51cSRene Gollent		float left = min_c(screen.Frame().right - width, frame.left);
445ce59b51cSRene Gollent		float top = min_c(screen.Frame().bottom - height, frame.top);
446ce59b51cSRene Gollent		MoveTo(left, top);
447ce59b51cSRene Gollent	}
448ce59b51cSRene Gollent
449ce59b51cSRene Gollent	for (int i = 0; i < fColumnListView->CountColumns(); i++) {
450ce59b51cSRene Gollent		CLVColumn* column = fColumnListView->ColumnAt(i);
451ce59b51cSRene Gollent		float columnWidth;
452ce59b51cSRene Gollent		if (loadMsg.FindFloat("column width", i, &columnWidth) == B_OK)
453ce59b51cSRene Gollent			column->SetWidth(max_c(column->Width(), columnWidth));
454ce59b51cSRene Gollent	}
455ce59b51cSRene Gollent}
456ce59b51cSRene Gollent
457ce59b51cSRene Gollent
4586c333678SFredrik Modeen// Creates a new entry and adds it to the GUI. (defaultCommand) will be the
4596c333678SFredrik Modeen// text in the entry, or NULL if no text is desired.
4606c333678SFredrik Modeenvoid
4616c333678SFredrik ModeenShortcutsWindow::_AddNewSpec(const char* defaultCommand)
4626c333678SFredrik Modeen{
4636c333678SFredrik Modeen	_MarkKeySetModified();
4646c333678SFredrik Modeen
4656c333678SFredrik Modeen	ShortcutsSpec* spec;
4666c333678SFredrik Modeen	int curSel = fColumnListView->CurrentSelection();
4676c333678SFredrik Modeen	if (curSel >= 0) {
4686c333678SFredrik Modeen		spec = new ShortcutsSpec(*((ShortcutsSpec*)
4696c333678SFredrik Modeen			fColumnListView->ItemAt(curSel)));
4706c333678SFredrik Modeen
4716c333678SFredrik Modeen		if (defaultCommand)
4726c333678SFredrik Modeen			spec->SetCommand(defaultCommand);
4736c333678SFredrik Modeen	} else
4746c333678SFredrik Modeen		spec = new ShortcutsSpec(defaultCommand ? defaultCommand : "");
4756c333678SFredrik Modeen
4766c333678SFredrik Modeen	fColumnListView->AddItem(spec);
4776c333678SFredrik Modeen	fColumnListView->Select(fColumnListView->CountItems() - 1);
4786c333678SFredrik Modeen	fColumnListView->ScrollToSelection();
4796c333678SFredrik Modeen}
4806c333678SFredrik Modeen
4816c333678SFredrik Modeen
4826c333678SFredrik Modeenvoid
4836c333678SFredrik ModeenShortcutsWindow::MessageReceived(BMessage* msg)
4846c333678SFredrik Modeen{
4856c333678SFredrik Modeen	switch(msg->what) {
4866c333678SFredrik Modeen		case OPEN_KEYSET:
4876c333678SFredrik Modeen		case APPEND_KEYSET:
4886c333678SFredrik Modeen			fLastOpenWasAppend = (msg->what == APPEND_KEYSET);
4896c333678SFredrik Modeen			if (fOpenPanel)
4906c333678SFredrik Modeen				fOpenPanel->Show();
4916c333678SFredrik Modeen			else {
4926c333678SFredrik Modeen				BMessenger m(this);
4936c333678SFredrik Modeen				fOpenPanel = new BFilePanel(B_OPEN_PANEL, &m, NULL, 0, false);
4946c333678SFredrik Modeen				fOpenPanel->Show();
4956c333678SFredrik Modeen			}
4966c333678SFredrik Modeen			fOpenPanel->SetButtonLabel(B_DEFAULT_BUTTON, fLastOpenWasAppend ?
4973672a07eSStephan Aßmus				B_TRANSLATE("Append") : B_TRANSLATE("Open"));
4983672a07eSStephan Aßmus			break;
4996c333678SFredrik Modeen
5006c333678SFredrik Modeen		case REVERT_KEYSET:
5016c333678SFredrik Modeen		{
5026c333678SFredrik Modeen			// Send a message to myself, to get me to reload the settings file
5036c333678SFredrik Modeen			fLastOpenWasAppend = false;
5046c333678SFredrik Modeen			BMessage reload(B_REFS_RECEIVED);
5056c333678SFredrik Modeen			entry_ref eref;
5066c333678SFredrik Modeen			_GetSettingsFile(&eref);
5076c333678SFredrik Modeen			reload.AddRef("refs", &eref);
5086c333678SFredrik Modeen			reload.AddString("startupRef", "yeah");
5096c333678SFredrik Modeen			PostMessage(&reload);
5103672a07eSStephan Aßmus			break;
5116c333678SFredrik Modeen		}
5126c333678SFredrik Modeen
5136c333678SFredrik Modeen		// Respond to drag-and-drop messages here
5146c333678SFredrik Modeen		case B_SIMPLE_DATA:
5156c333678SFredrik Modeen		{
5166c333678SFredrik Modeen			int i = 0;
5176c333678SFredrik Modeen
5186c333678SFredrik Modeen			entry_ref ref;
5193672a07eSStephan Aßmus			while (msg->FindRef("refs", i++, &ref) == B_OK) {
5206c333678SFredrik Modeen				BEntry entry(&ref);
5213672a07eSStephan Aßmus				if (entry.InitCheck() == B_OK) {
5226c333678SFredrik Modeen					BPath path(&entry);
5236c333678SFredrik Modeen
5243672a07eSStephan Aßmus					if (path.InitCheck() == B_OK) {
5256c333678SFredrik Modeen						// Add a new item with the given path.
5266c333678SFredrik Modeen						BString str(path.Path());
5276c333678SFredrik Modeen						DoStandardEscapes(str);
5286c333678SFredrik Modeen						_AddNewSpec(str.String());
5296c333678SFredrik Modeen					}
5306c333678SFredrik Modeen				}
5316c333678SFredrik Modeen			}
5323672a07eSStephan Aßmus			break;
5336c333678SFredrik Modeen		}
5346c333678SFredrik Modeen
5356c333678SFredrik Modeen		// Respond to FileRequester's messages here
5366c333678SFredrik Modeen		case B_REFS_RECEIVED:
5376c333678SFredrik Modeen		{
5386c333678SFredrik Modeen			// Find file ref
5396c333678SFredrik Modeen			entry_ref ref;
5406c333678SFredrik Modeen			bool isStartMsg = msg->HasString("startupRef");
5413672a07eSStephan Aßmus			if (msg->FindRef("refs", &ref) == B_OK) {
5426c333678SFredrik Modeen				// load the file into (fileMsg)
5436c333678SFredrik Modeen				BMessage fileMsg;
5446c333678SFredrik Modeen				{
5456c333678SFredrik Modeen					BFile file(&ref, B_READ_ONLY);
5463672a07eSStephan Aßmus					if ((file.InitCheck() != B_OK)
5473672a07eSStephan Aßmus						|| (fileMsg.Unflatten(&file) != B_OK)) {
5486c333678SFredrik Modeen						if (isStartMsg) {
5496c333678SFredrik Modeen							// use this to save to anyway
5506c333678SFredrik Modeen							fLastSaved = BEntry(&ref);
5516c333678SFredrik Modeen							break;
5526c333678SFredrik Modeen						} else {
5536c333678SFredrik Modeen							(new BAlert(ERROR,
5543672a07eSStephan Aßmus								B_TRANSLATE("Shortcuts was couldn't open your "
5553672a07eSStephan Aßmus								"KeySet file!"), B_TRANSLATE("OK")))->Go(NULL);
5566c333678SFredrik Modeen							break;
5576c333678SFredrik Modeen						}
5586c333678SFredrik Modeen					}
5596c333678SFredrik Modeen				}
5606c333678SFredrik Modeen
5616c333678SFredrik Modeen				if (fLastOpenWasAppend == false) {
5626c333678SFredrik Modeen					// Clear the menu...
5633672a07eSStephan Aßmus					while (ShortcutsSpec* item
5643672a07eSStephan Aßmus						= ((ShortcutsSpec*)fColumnListView->RemoveItem(0L))) {
5653672a07eSStephan Aßmus						delete item;
5663672a07eSStephan Aßmus					}
5676c333678SFredrik Modeen				}
5686c333678SFredrik Modeen
5696c333678SFredrik Modeen				if (_LoadKeySet(fileMsg)) {
5706c333678SFredrik Modeen					if (isStartMsg) fLastSaved = BEntry(&ref);
5716c333678SFredrik Modeen					fSaveButton->SetEnabled(isStartMsg == false);
5726c333678SFredrik Modeen
5736c333678SFredrik Modeen					// If we just loaded in the Shortcuts settings file, then
5746c333678SFredrik Modeen					// no need to tell the user to save on exit.
5756c333678SFredrik Modeen					entry_ref eref;
5766c333678SFredrik Modeen					_GetSettingsFile(&eref);
5776c333678SFredrik Modeen					if (ref == eref) fKeySetModified = false;
5786c333678SFredrik Modeen				} else {
5796c333678SFredrik Modeen					(new BAlert(ERROR,
5803672a07eSStephan Aßmus						B_TRANSLATE("Shortcuts was unable to parse your "
5813672a07eSStephan Aßmus						"KeySet file!"),
5823672a07eSStephan Aßmus						B_TRANSLATE("OK")))->Go(NULL);
5836c333678SFredrik Modeen					break;
5846c333678SFredrik Modeen				}
5856c333678SFredrik Modeen			}
5863672a07eSStephan Aßmus			break;
5876c333678SFredrik Modeen		}
5886c333678SFredrik Modeen
5896c333678SFredrik Modeen		// These messages come from the pop-up menu of the Applications column
5906c333678SFredrik Modeen		case SELECT_APPLICATION:
5916c333678SFredrik Modeen		{
5926c333678SFredrik Modeen			int csel = fColumnListView->CurrentSelection();
5936c333678SFredrik Modeen			if (csel >= 0) {
5946c333678SFredrik Modeen				entry_ref aref;
5953672a07eSStephan Aßmus				if (msg->FindRef("refs", &aref) == B_OK) {
5966c333678SFredrik Modeen					BEntry ent(&aref);
5973672a07eSStephan Aßmus					if (ent.InitCheck() == B_OK) {
5986c333678SFredrik Modeen						BPath path;
5993672a07eSStephan Aßmus						if ((ent.GetPath(&path) == B_OK)
6006c333678SFredrik Modeen							&& (((ShortcutsSpec *)
6016c333678SFredrik Modeen							fColumnListView->ItemAt(csel))->
6026c333678SFredrik Modeen							ProcessColumnTextString(ShortcutsSpec::
6036c333678SFredrik Modeen							STRING_COLUMN_INDEX, path.Path()))) {
6046c333678SFredrik Modeen
6056c333678SFredrik Modeen							fColumnListView->InvalidateItem(csel);
6066c333678SFredrik Modeen							_MarkKeySetModified();
6076c333678SFredrik Modeen						}
6086c333678SFredrik Modeen					}
6096c333678SFredrik Modeen				}
6106c333678SFredrik Modeen			}
6113672a07eSStephan Aßmus			break;
6126c333678SFredrik Modeen		}
6136c333678SFredrik Modeen
6146c333678SFredrik Modeen		case SAVE_KEYSET:
6156c333678SFredrik Modeen		{
6166c333678SFredrik Modeen			bool showSaveError = false;
6176c333678SFredrik Modeen
6186c333678SFredrik Modeen			const char * name;
6196c333678SFredrik Modeen			entry_ref entry;
6203672a07eSStephan Aßmus			if ((msg->FindString("name", &name) == B_OK)
6213672a07eSStephan Aßmus				&& (msg->FindRef("directory", &entry) == B_OK)) {
6226c333678SFredrik Modeen				BDirectory dir(&entry);
6236c333678SFredrik Modeen				BEntry saveTo(&dir, name, true);
6243672a07eSStephan Aßmus				showSaveError = ((saveTo.InitCheck() != B_OK)
6256c333678SFredrik Modeen				|| (_SaveKeySet(saveTo) == false));
6263672a07eSStephan Aßmus			} else if (fLastSaved.InitCheck() == B_OK) {
6276c333678SFredrik Modeen				// We've saved this before, save over previous file.
6286c333678SFredrik Modeen				showSaveError = (_SaveKeySet(fLastSaved) == false);
6296c333678SFredrik Modeen			} else PostMessage(SAVE_KEYSET_AS); // open the save requester...
6306c333678SFredrik Modeen
6316c333678SFredrik Modeen			if (showSaveError) {
6323672a07eSStephan Aßmus				(new BAlert(ERROR,
6333672a07eSStephan Aßmus					B_TRANSLATE("Shortcuts wasn't able to save your keyset."),
6343672a07eSStephan Aßmus					B_TRANSLATE("OK")))->Go(NULL);
6356c333678SFredrik Modeen			}
6363672a07eSStephan Aßmus			break;
6376c333678SFredrik Modeen		}
6386c333678SFredrik Modeen
6396c333678SFredrik Modeen		case SAVE_KEYSET_AS:
6406c333678SFredrik Modeen		{
6416c333678SFredrik Modeen			if (fSavePanel)
6426c333678SFredrik Modeen				fSavePanel->Show();
6436c333678SFredrik Modeen			else {
6446c333678SFredrik Modeen				BMessage msg(SAVE_KEYSET);
6456c333678SFredrik Modeen				BMessenger messenger(this);
6466c333678SFredrik Modeen				fSavePanel = new BFilePanel(B_SAVE_PANEL, &messenger, NULL, 0,
6476c333678SFredrik Modeen					false, &msg);
6486c333678SFredrik Modeen				fSavePanel->Show();
6496c333678SFredrik Modeen			}
6503672a07eSStephan Aßmus			break;
6516c333678SFredrik Modeen		}
6526c333678SFredrik Modeen
6536c333678SFredrik Modeen		case ADD_HOTKEY_ITEM:
6546c333678SFredrik Modeen			_AddNewSpec(NULL);
6553672a07eSStephan Aßmus			break;
6566c333678SFredrik Modeen
6576c333678SFredrik Modeen		case REMOVE_HOTKEY_ITEM:
6586c333678SFredrik Modeen		{
6596c333678SFredrik Modeen			int index = fColumnListView->CurrentSelection();
6606c333678SFredrik Modeen			if (index >= 0) {
6616c333678SFredrik Modeen				CLVListItem* item = (CLVListItem*)
6626c333678SFredrik Modeen					fColumnListView->ItemAt(index);
6636c333678SFredrik Modeen				fColumnListView->RemoveItem(index);
6646c333678SFredrik Modeen				delete item;
6656c333678SFredrik Modeen				_MarkKeySetModified();
6666c333678SFredrik Modeen
6676c333678SFredrik Modeen				// Rules for new selection: If there is an item at (index),
6686c333678SFredrik Modeen				// select it. Otherwise, if there is an item at (index-1),
6696c333678SFredrik Modeen				// select it. Otherwise, select nothing.
6706c333678SFredrik Modeen				int num = fColumnListView->CountItems();
6716c333678SFredrik Modeen				if (num > 0) {
6726c333678SFredrik Modeen					if (index < num)
6736c333678SFredrik Modeen						fColumnListView->Select(index);
6746c333678SFredrik Modeen					else {
6756c333678SFredrik Modeen						if (index > 0)
6766c333678SFredrik Modeen							index--;
6776c333678SFredrik Modeen						if (index < num)
6786c333678SFredrik Modeen							fColumnListView->Select(index);
6796c333678SFredrik Modeen					}
6806c333678SFredrik Modeen				}
6816c333678SFredrik Modeen			}
6823672a07eSStephan Aßmus			break;
6836c333678SFredrik Modeen		}
6846c333678SFredrik Modeen
6856c333678SFredrik Modeen		// Received when the user clicks on the ColumnListView
6866c333678SFredrik Modeen		case HOTKEY_ITEM_SELECTED:
6876c333678SFredrik Modeen		{
6886c333678SFredrik Modeen			int32 index = -1;
6896c333678SFredrik Modeen			msg->FindInt32("index", &index);
6906c333678SFredrik Modeen			bool validItem = (index >= 0);
6916c333678SFredrik Modeen			fRemoveButton->SetEnabled(validItem);
6923672a07eSStephan Aßmus			break;
6936c333678SFredrik Modeen		}
6946c333678SFredrik Modeen
6956c333678SFredrik Modeen		// Received when an entry is to be modified in response to GUI activity
6966c333678SFredrik Modeen		case HOTKEY_ITEM_MODIFIED:
6976c333678SFredrik Modeen		{
6986c333678SFredrik Modeen			int32 row, column;
6996c333678SFredrik Modeen
7003672a07eSStephan Aßmus			if ((msg->FindInt32("row", &row) == B_OK)
7013672a07eSStephan Aßmus				&& (msg->FindInt32("column", &column) == B_OK)) {
7026c333678SFredrik Modeen				int32 key;
7036c333678SFredrik Modeen				const char* bytes;
7046c333678SFredrik Modeen
7056c333678SFredrik Modeen				if (row >= 0) {
7066c333678SFredrik Modeen					ShortcutsSpec* item = (ShortcutsSpec*)
7076c333678SFredrik Modeen						fColumnListView->ItemAt(row);
7086c333678SFredrik Modeen					bool repaintNeeded = false; // default
7096c333678SFredrik Modeen
7106c333678SFredrik Modeen					if (msg->HasInt32("mouseClick")) {
7116c333678SFredrik Modeen						repaintNeeded = item->ProcessColumnMouseClick(column);
7123672a07eSStephan Aßmus					} else if ((msg->FindString("bytes", &bytes) == B_OK)
7133672a07eSStephan Aßmus						&& (msg->FindInt32("key", &key) == B_OK)) {
7146c333678SFredrik Modeen						repaintNeeded = item->ProcessColumnKeyStroke(column,
7156c333678SFredrik Modeen							bytes, key);
7166c333678SFredrik Modeen					} else if (msg->FindInt32("unmappedkey", &key) ==
7173672a07eSStephan Aßmus						B_OK) {
7186c333678SFredrik Modeen						repaintNeeded = ((column == item->KEY_COLUMN_INDEX)
7196c333678SFredrik Modeen							&& ((key > 0xFF) || (GetKeyName(key) != NULL))
7206c333678SFredrik Modeen							&& (item->ProcessColumnKeyStroke(column, NULL,
7216c333678SFredrik Modeen							key)));
7223672a07eSStephan Aßmus					} else if (msg->FindString("text", &bytes) == B_OK) {
7236c333678SFredrik Modeen						if ((bytes[0] == '(')&&(bytes[1] == 'C')) {
7246c333678SFredrik Modeen							if (fSelectPanel)
7256c333678SFredrik Modeen								fSelectPanel->Show();
7266c333678SFredrik Modeen							else {
7276c333678SFredrik Modeen								BMessage msg(SELECT_APPLICATION);
7286c333678SFredrik Modeen								BMessenger m(this);
7296c333678SFredrik Modeen								fSelectPanel = new BFilePanel(B_OPEN_PANEL, &m,
7306c333678SFredrik Modeen									NULL, 0, false, &msg);
7316c333678SFredrik Modeen								fSelectPanel->Show();
7326c333678SFredrik Modeen							}
7336c333678SFredrik Modeen							fSelectPanel->SetButtonLabel(B_DEFAULT_BUTTON,
7343672a07eSStephan Aßmus								B_TRANSLATE("Select"));
7353672a07eSStephan Aßmus						} else {
7366c333678SFredrik Modeen							repaintNeeded = item->ProcessColumnTextString(
7376c333678SFredrik Modeen								column, bytes);
7383672a07eSStephan Aßmus						}
7396c333678SFredrik Modeen					}
7406c333678SFredrik Modeen
7416c333678SFredrik Modeen					if (repaintNeeded) {
7426c333678SFredrik Modeen						fColumnListView->InvalidateItem(row);
7436c333678SFredrik Modeen						_MarkKeySetModified();
7446c333678SFredrik Modeen					}
7456c333678SFredrik Modeen				}
7466c333678SFredrik Modeen			}
7473672a07eSStephan Aßmus			break;
7486c333678SFredrik Modeen		}
7496c333678SFredrik Modeen
7506c333678SFredrik Modeen		default:
7516c333678SFredrik Modeen			BWindow::MessageReceived(msg);
7523672a07eSStephan Aßmus			break;
7536c333678SFredrik Modeen	}
7546c333678SFredrik Modeen}
7556c333678SFredrik Modeen
7566c333678SFredrik Modeen
7576c333678SFredrik Modeenvoid
7586c333678SFredrik ModeenShortcutsWindow::_MarkKeySetModified()
7596c333678SFredrik Modeen{
7606c333678SFredrik Modeen	if (fKeySetModified == false) {
7616c333678SFredrik Modeen		fKeySetModified = true;
7626c333678SFredrik Modeen		fSaveButton->SetEnabled(true);
7636c333678SFredrik Modeen	}
7646c333678SFredrik Modeen}
7656c333678SFredrik Modeen
7666c333678SFredrik Modeen
7676c333678SFredrik Modeenvoid
7686c333678SFredrik ModeenShortcutsWindow::Quit()
769