ShortcutsWindow.cpp revision fa1ee6d4
16c333678SFredrik Modeen/*
26c333678SFredrik Modeen * Copyright 1999-2009 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>
186c333678SFredrik Modeen#include <Clipboard.h>
19fa1ee6d4SJonas Sundström#include <File.h>
20fa1ee6d4SJonas Sundström#include <FindDirectory.h>
21fa1ee6d4SJonas Sundström#include <Input.h>
226c333678SFredrik Modeen#include <Menu.h>
236c333678SFredrik Modeen#include <MenuBar.h>
24fa1ee6d4SJonas Sundström#include <MenuItem.h>
25fa1ee6d4SJonas Sundström#include <MessageFilter.h>
26fa1ee6d4SJonas Sundström#include <Path.h>
27fa1ee6d4SJonas Sundström#include <PopUpMenu.h>
286c333678SFredrik Modeen#include <ScrollBar.h>
296c333678SFredrik Modeen#include <ScrollView.h>
306c333678SFredrik Modeen#include <String.h>
316c333678SFredrik Modeen
326c333678SFredrik Modeen#include "ColumnListView.h"
336c333678SFredrik Modeen
346c333678SFredrik Modeen#include "KeyInfos.h"
356c333678SFredrik Modeen#include "MetaKeyStateMap.h"
36fa1ee6d4SJonas Sundström#include "ParseCommandLine.h"
376c333678SFredrik Modeen#include "ShortcutsFilterConstants.h"
38fa1ee6d4SJonas Sundström#include "ShortcutsSpec.h"
39fa1ee6d4SJonas Sundström
406c333678SFredrik Modeen
416c333678SFredrik Modeen// Window sizing constraints
426c333678SFredrik Modeen#define MIN_WIDTH	600
436c333678SFredrik Modeen#define MIN_HEIGHT	130
446c333678SFredrik Modeen#define MAX_WIDTH	65535
456c333678SFredrik Modeen#define MAX_HEIGHT	65535
466c333678SFredrik Modeen
476c333678SFredrik Modeen// Default window position
486c333678SFredrik Modeen#define WINDOW_START_X 30
496c333678SFredrik Modeen#define WINDOW_START_Y 100
506c333678SFredrik Modeen
516c333678SFredrik Modeen#define ERROR "Shortcuts Error"
526c333678SFredrik Modeen#define WARNING "Shortcuts warning"
536c333678SFredrik Modeen
546c333678SFredrik Modeen// Global constants for Shortcuts
556c333678SFredrik Modeen#define V_SPACING 5 // vertical spacing between GUI components
566c333678SFredrik Modeen
576c333678SFredrik Modeen
586c333678SFredrik Modeen// Creates a pop-up-menu that reflects the possible states of the specified
596c333678SFredrik Modeen// meta-key.
606c333678SFredrik Modeenstatic BPopUpMenu* CreateMetaPopUp(int col);
616c333678SFredrik Modeenstatic BPopUpMenu* CreateMetaPopUp(int col)
626c333678SFredrik Modeen{
636c333678SFredrik Modeen	MetaKeyStateMap& map = GetNthKeyMap(col);
646c333678SFredrik Modeen	BPopUpMenu * popup = new BPopUpMenu(NULL, false);
656c333678SFredrik Modeen	int numStates = map.GetNumStates();
666c333678SFredrik Modeen
676c333678SFredrik Modeen	for (int i = 0; i < numStates; i++)
686c333678SFredrik Modeen		popup->AddItem(new BMenuItem(map.GetNthStateDesc(i), NULL));
696c333678SFredrik Modeen
706c333678SFredrik Modeen	return popup;
716c333678SFredrik Modeen}
726c333678SFredrik Modeen
73fa1ee6d4SJonas Sundström
746c333678SFredrik Modeen// Creates a pop-up that allows the user to choose a key-cap visually
756c333678SFredrik Modeenstatic BPopUpMenu* CreateKeysPopUp();
766c333678SFredrik Modeenstatic BPopUpMenu* CreateKeysPopUp()
776c333678SFredrik Modeen{
786c333678SFredrik Modeen	BPopUpMenu* popup = new BPopUpMenu(NULL, false);
796c333678SFredrik Modeen	int numKeys = GetNumKeyIndices();
806c333678SFredrik Modeen	for (int i = 0; i < numKeys; i++) {
816c333678SFredrik Modeen		const char* next = GetKeyName(i);
826c333678SFredrik Modeen
836c333678SFredrik Modeen		if (next)
846c333678SFredrik Modeen			popup->AddItem(new BMenuItem(next, NULL));
856c333678SFredrik Modeen	}
866c333678SFredrik Modeen	return popup;
876c333678SFredrik Modeen}
886c333678SFredrik Modeen
896c333678SFredrik Modeen
906c333678SFredrik ModeenShortcutsWindow::ShortcutsWindow()
916c333678SFredrik Modeen	:
926c333678SFredrik Modeen	BWindow(BRect(WINDOW_START_X, WINDOW_START_Y, WINDOW_START_X + MIN_WIDTH,
936c333678SFredrik Modeen		WINDOW_START_Y + MIN_HEIGHT * 2), "Shortcuts", B_DOCUMENT_WINDOW, 0L),
946c333678SFredrik Modeen		fSavePanel(NULL),
956c333678SFredrik Modeen		fOpenPanel(NULL),
966c333678SFredrik Modeen		fSelectPanel(NULL),
976c333678SFredrik Modeen		fKeySetModified(false),
986c333678SFredrik Modeen		fLastOpenWasAppend(false)
996c333678SFredrik Modeen{
1006c333678SFredrik Modeen	InitializeMetaMaps();
1016c333678SFredrik Modeen	SetSizeLimits(MIN_WIDTH, MAX_WIDTH, MIN_HEIGHT, MAX_HEIGHT);
1026c333678SFredrik Modeen	BMenuBar* menuBar = new BMenuBar(BRect(0, 0, 0, 0), "Menu Bar");
1036c333678SFredrik Modeen
1046c333678SFredrik Modeen	BMenu* fileMenu = new BMenu("File");
1056c333678SFredrik Modeen	fileMenu->AddItem(new BMenuItem("Open KeySet...",
1066c333678SFredrik Modeen		new BMessage(OPEN_KEYSET), 'O'));
1076c333678SFredrik Modeen	fileMenu->AddItem(new BMenuItem("Append KeySet...",
1086c333678SFredrik Modeen		new BMessage(APPEND_KEYSET), 'A'));
1096c333678SFredrik Modeen	fileMenu->AddItem(new BMenuItem("Revert to Saved",
1106c333678SFredrik Modeen		new BMessage(REVERT_KEYSET), 'A'));
1116c333678SFredrik Modeen	fileMenu->AddItem(new BSeparatorItem);
1126c333678SFredrik Modeen	fileMenu->AddItem(new BMenuItem("Save KeySet As...",
1136c333678SFredrik Modeen		new BMessage(SAVE_KEYSET_AS), 'S'));
1146c333678SFredrik Modeen	fileMenu->AddItem(new BSeparatorItem);
115fa1ee6d4SJonas Sundström	fileMenu->AddItem(new BMenuItem("About Shortcuts",
116fa1ee6d4SJonas Sundström		new BMessage(B_ABOUT_REQUESTED)));
1176c333678SFredrik Modeen	fileMenu->AddItem(new BSeparatorItem);
1186c333678SFredrik Modeen	fileMenu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED),
1196c333678SFredrik Modeen		'Q'));
1206c333678SFredrik Modeen	menuBar->AddItem(fileMenu);
1216c333678SFredrik Modeen
1226c333678SFredrik Modeen	AddChild(menuBar);
1236c333678SFredrik Modeen
1246c333678SFredrik Modeen	font_height fh;
1256c333678SFredrik Modeen	be_plain_font->GetHeight(&fh);
1266c333678SFredrik Modeen	float vButtonHeight = ceil(fh.ascent) + ceil(fh.descent) + 5.0f;
1276c333678SFredrik Modeen
1286c333678SFredrik Modeen	BRect tableBounds = Bounds();
1296c333678SFredrik Modeen	tableBounds.top = menuBar->Bounds().bottom + 1;
1306c333678SFredrik Modeen	tableBounds.right -= B_V_SCROLL_BAR_WIDTH;
1316c333678SFredrik Modeen	tableBounds.bottom -= (B_H_SCROLL_BAR_HEIGHT + V_SPACING + vButtonHeight +
1326c333678SFredrik Modeen		V_SPACING * 2);
1336c333678SFredrik Modeen
1346c333678SFredrik Modeen	BScrollView* containerView;
1356c333678SFredrik Modeen	fColumnListView = new ColumnListView(tableBounds, &containerView, NULL,
1366c333678SFredrik Modeen		B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
1376c333678SFredrik Modeen		B_SINGLE_SELECTION_LIST, true, true, true, B_NO_BORDER);
1386c333678SFredrik Modeen
1396c333678SFredrik Modeen	fColumnListView->SetEditMessage(new BMessage(HOTKEY_ITEM_MODIFIED),
1406c333678SFredrik Modeen		BMessenger(this));
1416c333678SFredrik Modeen
1426c333678SFredrik Modeen	const float metaWidth = 50.0f;
1436c333678SFredrik Modeen
1446c333678SFredrik Modeen	for (int i = 0; i < ShortcutsSpec::NUM_META_COLUMNS; i++)
1456c333678SFredrik Modeen		fColumnListView->AddColumn(
1466c333678SFredrik Modeen			new CLVColumn(ShortcutsSpec::GetColumnName(i), CreateMetaPopUp(i),
1476c333678SFredrik Modeen			metaWidth, CLV_SORT_KEYABLE));
1486c333678SFredrik Modeen
1496c333678SFredrik Modeen	fColumnListView->AddColumn(new CLVColumn("Key", CreateKeysPopUp(), 60,
1506c333678SFredrik Modeen		CLV_SORT_KEYABLE));
1516c333678SFredrik Modeen
1526c333678SFredrik Modeen	BPopUpMenu* popup = new BPopUpMenu(NULL, false);
1536c333678SFredrik Modeen	popup->AddItem(new BMenuItem("(Choose App with File Requester)", NULL));
1546c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*InsertString \"Your Text Here\"", NULL));
1556c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*MoveMouse +20 +0", NULL));
1566c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*MoveMouseTo 50% 50%", NULL));
1576c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*MouseButton 1", NULL));
1586c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*LaunchHandler text/html", NULL));
1596c333678SFredrik Modeen	popup->AddItem(new BMenuItem(
1606c333678SFredrik Modeen		"*Multi \"*MoveMouseTo 100% 0\" \"*MouseButton 1\"", NULL));
1616c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*MouseDown", NULL));
1626c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*MouseUp", NULL));
1636c333678SFredrik Modeen	popup->AddItem(new BMenuItem(
1646c333678SFredrik Modeen		"*SendMessage application/x-vnd.Be-TRAK 'Tfnd'", NULL));
1656c333678SFredrik Modeen	popup->AddItem(new BMenuItem("*Beep", NULL));
1666c333678SFredrik Modeen	fColumnListView->AddColumn(new CLVColumn("Application", popup, 323.0,
1676c333678SFredrik Modeen		CLV_SORT_KEYABLE));
1686c333678SFredrik Modeen
1696c333678SFredrik Modeen	fColumnListView->SetSortFunction(ShortcutsSpec::MyCompare);
1706c333678SFredrik Modeen	AddChild(containerView);
1716c333678SFredrik Modeen
1726c333678SFredrik Modeen	fColumnListView->SetSelectionMessage(new BMessage(HOTKEY_ITEM_SELECTED));
1736c333678SFredrik Modeen	fColumnListView->SetTarget(this);
1746c333678SFredrik Modeen
1756c333678SFredrik Modeen	BRect buttonBounds = Bounds();
1766c333678SFredrik Modeen	buttonBounds.left += V_SPACING;
1776c333678SFredrik Modeen	buttonBounds.right = ((buttonBounds.right - buttonBounds.left) / 2.0f) +
1786c333678SFredrik Modeen		buttonBounds.left;
1796c333678SFredrik Modeen	buttonBounds.bottom -= V_SPACING * 2;
1806c333678SFredrik Modeen	buttonBounds.top = buttonBounds.bottom - vButtonHeight;
1816c333678SFredrik Modeen	buttonBounds.right -= B_V_SCROLL_BAR_WIDTH;
1826c333678SFredrik Modeen	float origRight = buttonBounds.right;
1836c333678SFredrik Modeen	buttonBounds.right = (buttonBounds.left + origRight) * 0.40f -
1846c333678SFredrik Modeen		(V_SPACING / 2);
1856c333678SFredrik Modeen	AddChild(fAddButton = new ResizableButton(Bounds(), buttonBounds, "add",
1866c333678SFredrik Modeen		"Add New Shortcut", new BMessage(ADD_HOTKEY_ITEM)));
1876c333678SFredrik Modeen	buttonBounds.left = buttonBounds.right + V_SPACING;
1886c333678SFredrik Modeen	buttonBounds.right = origRight;
1896c333678SFredrik Modeen	AddChild(fRemoveButton = new ResizableButton(Bounds(), buttonBounds,
1906c333678SFredrik Modeen		"remove", "Remove Selected Shortcut",
1916c333678SFredrik Modeen		new BMessage(REMOVE_HOTKEY_ITEM)));
1926c333678SFredrik Modeen
1936c333678SFredrik Modeen	fRemoveButton->SetEnabled(false);
1946c333678SFredrik Modeen
1956c333678SFredrik Modeen	float offset = (buttonBounds.right - buttonBounds.left) / 2.0f;
1966c333678SFredrik Modeen	BRect saveButtonBounds = buttonBounds;
1976c333678SFredrik Modeen	saveButtonBounds.right = Bounds().right - B_V_SCROLL_BAR_WIDTH - offset;
1986c333678SFredrik Modeen	saveButtonBounds.left = buttonBounds.right + V_SPACING + offset;
1996c333678SFredrik Modeen	AddChild(fSaveButton = new ResizableButton(Bounds(), saveButtonBounds,
2006c333678SFredrik Modeen		"save", "Save & Apply", new BMessage(SAVE_KEYSET)));
2016c333678SFredrik Modeen
2026c333678SFredrik Modeen	fSaveButton->SetEnabled(false);
2036c333678SFredrik Modeen
2046c333678SFredrik Modeen	entry_ref ref;
2056c333678SFredrik Modeen	if (_GetSettingsFile(&ref)) {
2066c333678SFredrik Modeen		BMessage msg(B_REFS_RECEIVED);
2076c333678SFredrik Modeen		msg.AddRef("refs", &ref);
2086c333678SFredrik Modeen		msg.AddString("startupRef", "please");
2096c333678SFredrik Modeen		PostMessage(&msg); // Tell ourself to load this file if it exists.
2106c333678SFredrik Modeen	}
2116c333678SFredrik Modeen	Show();
2126c333678SFredrik Modeen}
2136c333678SFredrik Modeen
2146c333678SFredrik Modeen
2156c333678SFredrik ModeenShortcutsWindow::~ShortcutsWindow()
2166c333678SFredrik Modeen{
2176c333678SFredrik Modeen	delete fSavePanel;
2186c333678SFredrik Modeen	delete fOpenPanel;
2196c333678SFredrik Modeen	delete fSelectPanel;
2206c333678SFredrik Modeen	be_app->PostMessage(B_QUIT_REQUESTED);
2216c333678SFredrik Modeen}
2226c333678SFredrik Modeen
2236c333678SFredrik Modeen
2246c333678SFredrik Modeenbool
2256c333678SFredrik ModeenShortcutsWindow::QuitRequested()
2266c333678SFredrik Modeen{
2276c333678SFredrik Modeen	bool ret = true;
2286c333678SFredrik Modeen
2296c333678SFredrik Modeen	if (fKeySetModified) {
2306c333678SFredrik Modeen		BAlert* alert = new BAlert(WARNING,
2316c333678SFredrik Modeen			"Really quit without saving your changes?", "Don't Save", "Cancel",
2326c333678SFredrik Modeen			"Save");
2336c333678SFredrik Modeen		switch(alert->Go()) {
2346c333678SFredrik Modeen			case 1:
2356c333678SFredrik Modeen				ret = false;
2366c333678SFredrik Modeen			break;
2376c333678SFredrik Modeen
2386c333678SFredrik Modeen			case 2:
2396c333678SFredrik Modeen				// Save: automatically if possible, otherwise go back and open
2406c333678SFredrik Modeen				// up the file requester
2416c333678SFredrik Modeen				if (fLastSaved.InitCheck() == B_NO_ERROR) {
2426c333678SFredrik Modeen					if (_SaveKeySet(fLastSaved) == false) {
2436c333678SFredrik Modeen						(new BAlert(ERROR,
2446c333678SFredrik Modeen							"Shortcuts was unable to save your KeySet file!",
2456c333678SFredrik Modeen							"Oh no"))->Go();
2466c333678SFredrik Modeen						ret = true; //quit anyway
2476c333678SFredrik Modeen					}
2486c333678SFredrik Modeen				} else {
2496c333678SFredrik Modeen					PostMessage(SAVE_KEYSET);
2506c333678SFredrik Modeen					ret = false;
2516c333678SFredrik Modeen				}
2526c333678SFredrik Modeen			break;
2536c333678SFredrik Modeen			default:
2546c333678SFredrik Modeen				ret = true;
2556c333678SFredrik Modeen			break;
2566c333678SFredrik Modeen		}
2576c333678SFredrik Modeen	}
2586c333678SFredrik Modeen
2596c333678SFredrik Modeen	if (ret)
260fa1ee6d4SJonas Sundström		fColumnListView->DeselectAll();
2616c333678SFredrik Modeen	return ret;
2626c333678SFredrik Modeen}
2636c333678SFredrik Modeen
2646c333678SFredrik Modeen
2656c333678SFredrik Modeenbool
2666c333678SFredrik ModeenShortcutsWindow::_GetSettingsFile(entry_ref* eref)
2676c333678SFredrik Modeen{
2686c333678SFredrik Modeen	BPath path;
2696c333678SFredrik Modeen	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
2706c333678SFredrik Modeen		return false;
2716c333678SFredrik Modeen	else
2726c333678SFredrik Modeen		path.Append(SHORTCUTS_SETTING_FILE_NAME);
2736c333678SFredrik Modeen
2746c333678SFredrik Modeen	if (BEntry(path.Path(), true).GetRef(eref) == B_NO_ERROR)
2756c333678SFredrik Modeen		return true;
2766c333678SFredrik Modeen	else
2776c333678SFredrik Modeen		return false;
2786c333678SFredrik Modeen}
2796c333678SFredrik Modeen
2806c333678SFredrik Modeen
2816c333678SFredrik Modeen// Saves a settings file to (saveEntry). Returns true iff successful.
2826c333678SFredrik Modeenbool
2836c333678SFredrik ModeenShortcutsWindow::_SaveKeySet(BEntry& saveEntry)
2846c333678SFredrik Modeen{
2856c333678SFredrik Modeen	BFile saveTo(&saveEntry, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
2866c333678SFredrik Modeen	if (saveTo.InitCheck() != B_NO_ERROR)
2876c333678SFredrik Modeen		return false;
2886c333678SFredrik Modeen
2896c333678SFredrik Modeen	BMessage saveMsg;
2906c333678SFredrik Modeen	for (int i = 0; i < fColumnListView->CountItems(); i++) {
2916c333678SFredrik Modeen		BMessage next;
2926c333678SFredrik Modeen		if (((ShortcutsSpec*)fColumnListView->ItemAt(i))->Archive(&next)
2936c333678SFredrik Modeen			== B_NO_ERROR)
2946c333678SFredrik Modeen			saveMsg.AddMessage("spec", &next);
2956c333678SFredrik Modeen		else
2966c333678SFredrik Modeen			printf("Error archiving ShortcutsSpec #%i!\n",i);
2976c333678SFredrik Modeen	}
2986c333678SFredrik Modeen
2996c333678SFredrik Modeen	bool ret = (saveMsg.Flatten(&saveTo) == B_NO_ERROR);
3006c333678SFredrik Modeen
3016c333678SFredrik Modeen	if (ret) {
3026c333678SFredrik Modeen		fKeySetModified = false;
3036c333678SFredrik Modeen		fSaveButton->SetEnabled(false);
3046c333678SFredrik Modeen	}
3056c333678SFredrik Modeen
3066c333678SFredrik Modeen	return ret;
3076c333678SFredrik Modeen}
3086c333678SFredrik Modeen
3096c333678SFredrik Modeen
3106c333678SFredrik Modeen// Appends new entries from the file specified in the "spec" entry of
3116c333678SFredrik Modeen// (loadMsg). Returns true iff successful.
3126c333678SFredrik Modeenbool
3136c333678SFredrik ModeenShortcutsWindow::_LoadKeySet(const BMessage& loadMsg)
3146c333678SFredrik Modeen{
3156c333678SFredrik Modeen	int i = 0;
3166c333678SFredrik Modeen	BMessage msg;
3176c333678SFredrik Modeen	while (loadMsg.FindMessage("spec", i++, &msg) == B_NO_ERROR) {
3186c333678SFredrik Modeen		ShortcutsSpec* spec = (ShortcutsSpec*)ShortcutsSpec::Instantiate(&msg);
3196c333678SFredrik Modeen		if (spec != NULL)
3206c333678SFredrik Modeen			fColumnListView->AddItem(spec);
3216c333678SFredrik Modeen		else
3226c333678SFredrik Modeen			printf("_LoadKeySet: Error parsing spec!\n");
3236c333678SFredrik Modeen	}
3246c333678SFredrik Modeen	return true;
3256c333678SFredrik Modeen}
3266c333678SFredrik Modeen
3276c333678SFredrik Modeen
3286c333678SFredrik Modeen// Creates a new entry and adds it to the GUI. (defaultCommand) will be the
3296c333678SFredrik Modeen// text in the entry, or NULL if no text is desired.
3306c333678SFredrik Modeenvoid
3316c333678SFredrik ModeenShortcutsWindow::_AddNewSpec(const char* defaultCommand)
3326c333678SFredrik Modeen{
3336c333678SFredrik Modeen	_MarkKeySetModified();
3346c333678SFredrik Modeen
3356c333678SFredrik Modeen	ShortcutsSpec* spec;
3366c333678SFredrik Modeen	int curSel = fColumnListView->CurrentSelection();
3376c333678SFredrik Modeen	if (curSel >= 0) {
3386c333678SFredrik Modeen		spec = new ShortcutsSpec(*((ShortcutsSpec*)
3396c333678SFredrik Modeen			fColumnListView->ItemAt(curSel)));
3406c333678SFredrik Modeen
3416c333678SFredrik Modeen		if (defaultCommand)
3426c333678SFredrik Modeen			spec->SetCommand(defaultCommand);
3436c333678SFredrik Modeen	} else
3446c333678SFredrik Modeen		spec = new ShortcutsSpec(defaultCommand ? defaultCommand : "");
3456c333678SFredrik Modeen
3466c333678SFredrik Modeen	fColumnListView->AddItem(spec);
3476c333678SFredrik Modeen	fColumnListView->Select(fColumnListView->CountItems() - 1);
3486c333678SFredrik Modeen	fColumnListView->ScrollToSelection();
3496c333678SFredrik Modeen}
3506c333678SFredrik Modeen
3516c333678SFredrik Modeen
3526c333678SFredrik Modeenvoid
3536c333678SFredrik ModeenShortcutsWindow::MessageReceived(BMessage* msg)
3546c333678SFredrik Modeen{
3556c333678SFredrik Modeen	switch(msg->what) {
3566c333678SFredrik Modeen		case OPEN_KEYSET:
3576c333678SFredrik Modeen		case APPEND_KEYSET:
3586c333678SFredrik Modeen			fLastOpenWasAppend = (msg->what == APPEND_KEYSET);
3596c333678SFredrik Modeen			if (fOpenPanel)
3606c333678SFredrik Modeen				fOpenPanel->Show();
3616c333678SFredrik Modeen			else {
3626c333678SFredrik Modeen				BMessenger m(this);
3636c333678SFredrik Modeen				fOpenPanel = new BFilePanel(B_OPEN_PANEL, &m, NULL, 0, false);
3646c333678SFredrik Modeen				fOpenPanel->Show();
3656c333678SFredrik Modeen			}
3666c333678SFredrik Modeen			fOpenPanel->SetButtonLabel(B_DEFAULT_BUTTON, fLastOpenWasAppend ?
3676c333678SFredrik Modeen				"Append" : "Open");
3686c333678SFredrik Modeen		break;
3696c333678SFredrik Modeen
3706c333678SFredrik Modeen		case REVERT_KEYSET:
3716c333678SFredrik Modeen		{
3726c333678SFredrik Modeen			// Send a message to myself, to get me to reload the settings file
3736c333678SFredrik Modeen			fLastOpenWasAppend = false;
3746c333678SFredrik Modeen			BMessage reload(B_REFS_RECEIVED);
3756c333678SFredrik Modeen			entry_ref eref;
3766c333678SFredrik Modeen			_GetSettingsFile(&eref);
3776c333678SFredrik Modeen			reload.AddRef("refs", &eref);
3786c333678SFredrik Modeen			reload.AddString("startupRef", "yeah");
3796c333678SFredrik Modeen			PostMessage(&reload);
3806c333678SFredrik Modeen		}
3816c333678SFredrik Modeen		break;
3826c333678SFredrik Modeen
3836c333678SFredrik Modeen		// Respond to drag-and-drop messages here
3846c333678SFredrik Modeen		case B_SIMPLE_DATA:
3856c333678SFredrik Modeen		{
3866c333678SFredrik Modeen			int i = 0;
3876c333678SFredrik Modeen
3886c333678SFredrik Modeen			entry_ref ref;
3896c333678SFredrik Modeen			while (msg->FindRef("refs", i++, &ref) == B_NO_ERROR) {
3906c333678SFredrik Modeen				BEntry entry(&ref);
3916c333678SFredrik Modeen				if (entry.InitCheck() == B_NO_ERROR) {
3926c333678SFredrik Modeen					BPath path(&entry);
3936c333678SFredrik Modeen
3946c333678SFredrik Modeen					if (path.InitCheck() == B_NO_ERROR) {
3956c333678SFredrik Modeen						// Add a new item with the given path.
3966c333678SFredrik Modeen						BString str(path.Path());
3976c333678SFredrik Modeen						DoStandardEscapes(str);
3986c333678SFredrik Modeen						_AddNewSpec(str.String());
3996c333678SFredrik Modeen					}
4006c333678SFredrik Modeen				}
4016c333678SFredrik Modeen			}
4026c333678SFredrik Modeen		}
4036c333678SFredrik Modeen		break;
4046c333678SFredrik Modeen
4056c333678SFredrik Modeen		// Respond to FileRequester's messages here
4066c333678SFredrik Modeen		case B_REFS_RECEIVED:
4076c333678SFredrik Modeen		{
4086c333678SFredrik Modeen			// Find file ref
4096c333678SFredrik Modeen			entry_ref ref;
4106c333678SFredrik Modeen			bool isStartMsg = msg->HasString("startupRef");
4116c333678SFredrik Modeen			if (msg->FindRef("refs", &ref) == B_NO_ERROR) {
4126c333678SFredrik Modeen				// load the file into (fileMsg)
4136c333678SFredrik Modeen				BMessage fileMsg;
4146c333678SFredrik Modeen				{
4156c333678SFredrik Modeen					BFile file(&ref, B_READ_ONLY);
4166c333678SFredrik Modeen					if ((file.InitCheck() != B_NO_ERROR)
4176c333678SFredrik Modeen						|| (fileMsg.Unflatten(&file) != B_NO_ERROR)) {
4186c333678SFredrik Modeen						if (isStartMsg) {
4196c333678SFredrik Modeen							// use this to save to anyway
4206c333678SFredrik Modeen							fLastSaved = BEntry(&ref);
4216c333678SFredrik Modeen							break;
4226c333678SFredrik Modeen						} else {
4236c333678SFredrik Modeen							(new BAlert(ERROR,
4246c333678SFredrik Modeen								"Shortcuts was couldn't open your KeySet file!"
4256c333678SFredrik Modeen								, "Okay"))->Go(NULL);
4266c333678SFredrik Modeen							break;
4276c333678SFredrik Modeen						}
4286c333678SFredrik Modeen					}
4296c333678SFredrik Modeen				}
4306c333678SFredrik Modeen
4316c333678SFredrik Modeen				if (fLastOpenWasAppend == false) {
4326c333678SFredrik Modeen					// Clear the menu...
4336c333678SFredrik Modeen					ShortcutsSpec * item;
4346c333678SFredrik Modeen					do {
4356c333678SFredrik Modeen						delete (item = ((ShortcutsSpec*)
4366c333678SFredrik Modeen							fColumnListView->RemoveItem(int32(0))));
4376c333678SFredrik Modeen					} while (item);
4386c333678SFredrik Modeen				}
4396c333678SFredrik Modeen
4406c333678SFredrik Modeen				if (_LoadKeySet(fileMsg)) {
4416c333678SFredrik Modeen					if (isStartMsg) fLastSaved = BEntry(&ref);
4426c333678SFredrik Modeen					fSaveButton->SetEnabled(isStartMsg == false);
4436c333678SFredrik Modeen
4446c333678SFredrik Modeen					// If we just loaded in the Shortcuts settings file, then
4456c333678SFredrik Modeen					// no need to tell the user to save on exit.
4466c333678SFredrik Modeen					entry_ref eref;
4476c333678SFredrik Modeen					_GetSettingsFile(&eref);
4486c333678SFredrik Modeen					if (ref == eref) fKeySetModified = false;
4496c333678SFredrik Modeen				} else {
4506c333678SFredrik Modeen					(new BAlert(ERROR,
4516c333678SFredrik Modeen						"Shortcuts was unable to parse your KeySet file!",
4526c333678SFredrik Modeen						"Okay"))->Go(NULL);
4536c333678SFredrik Modeen					break;
4546c333678SFredrik Modeen				}
4556c333678SFredrik Modeen			}
4566c333678SFredrik Modeen		}
4576c333678SFredrik Modeen		break;
4586c333678SFredrik Modeen
4596c333678SFredrik Modeen		// These messages come from the pop-up menu of the Applications column
4606c333678SFredrik Modeen		case SELECT_APPLICATION:
4616c333678SFredrik Modeen		{
4626c333678SFredrik Modeen			int csel = fColumnListView->CurrentSelection();
4636c333678SFredrik Modeen			if (csel >= 0) {
4646c333678SFredrik Modeen				entry_ref aref;
4656c333678SFredrik Modeen				if (msg->FindRef("refs", &aref) == B_NO_ERROR) {
4666c333678SFredrik Modeen					BEntry ent(&aref);
4676c333678SFredrik Modeen					if (ent.InitCheck() == B_NO_ERROR) {
4686c333678SFredrik Modeen						BPath path;
4696c333678SFredrik Modeen						if ((ent.GetPath(&path) == B_NO_ERROR)
4706c333678SFredrik Modeen							&& (((ShortcutsSpec *)
4716c333678SFredrik Modeen							fColumnListView->ItemAt(csel))->
4726c333678SFredrik Modeen							ProcessColumnTextString(ShortcutsSpec::
4736c333678SFredrik Modeen							STRING_COLUMN_INDEX, path.Path()))) {
4746c333678SFredrik Modeen
4756c333678SFredrik Modeen							fColumnListView->InvalidateItem(csel);
4766c333678SFredrik Modeen							_MarkKeySetModified();
4776c333678SFredrik Modeen						}
4786c333678SFredrik Modeen					}
4796c333678SFredrik Modeen				}
4806c333678SFredrik Modeen			}
4816c333678SFredrik Modeen		}
4826c333678SFredrik Modeen		break;
4836c333678SFredrik Modeen
4846c333678SFredrik Modeen		case SAVE_KEYSET:
4856c333678SFredrik Modeen		{
4866c333678SFredrik Modeen			bool showSaveError = false;
4876c333678SFredrik Modeen
4886c333678SFredrik Modeen			const char * name;
4896c333678SFredrik Modeen			entry_ref entry;
4906c333678SFredrik Modeen			if ((msg->FindString("name", &name) == B_NO_ERROR)
4916c333678SFredrik Modeen				&& (msg->FindRef("directory", &entry) == B_NO_ERROR)) {
4926c333678SFredrik Modeen				BDirectory dir(&entry);
4936c333678SFredrik Modeen				BEntry saveTo(&dir, name, true);
4946c333678SFredrik Modeen				showSaveError = ((saveTo.InitCheck() != B_NO_ERROR)
4956c333678SFredrik Modeen				|| (_SaveKeySet(saveTo) == false));
4966c333678SFredrik Modeen			} else if (fLastSaved.InitCheck() == B_NO_ERROR) {
4976c333678SFredrik Modeen				// We've saved this before, save over previous file.
4986c333678SFredrik Modeen				showSaveError = (_SaveKeySet(fLastSaved) == false);
4996c333678SFredrik Modeen			} else PostMessage(SAVE_KEYSET_AS); // open the save requester...
5006c333678SFredrik Modeen
5016c333678SFredrik Modeen			if (showSaveError) {
5026c333678SFredrik Modeen				(new BAlert(ERROR, "Shortcuts wasn't able to save your keyset."
5036c333678SFredrik Modeen				, "Okay"))->Go(NULL);
5046c333678SFredrik Modeen			}
5056c333678SFredrik Modeen		}
5066c333678SFredrik Modeen		break;
5076c333678SFredrik Modeen
5086c333678SFredrik Modeen		case SAVE_KEYSET_AS:
5096c333678SFredrik Modeen		{
5106c333678SFredrik Modeen			if (fSavePanel)
5116c333678SFredrik Modeen				fSavePanel->Show();
5126c333678SFredrik Modeen			else {
5136c333678SFredrik Modeen				BMessage msg(SAVE_KEYSET);
5146c333678SFredrik Modeen				BMessenger messenger(this);
5156c333678SFredrik Modeen				fSavePanel = new BFilePanel(B_SAVE_PANEL, &messenger, NULL, 0,
5166c333678SFredrik Modeen					false, &msg);
5176c333678SFredrik Modeen				fSavePanel->Show();
5186c333678SFredrik Modeen			}
5196c333678SFredrik Modeen		}
5206c333678SFredrik Modeen		break;
5216c333678SFredrik Modeen
5226c333678SFredrik Modeen		case B_ABOUT_REQUESTED:
5236c333678SFredrik Modeen			be_app_messenger.SendMessage(B_ABOUT_REQUESTED);
5246c333678SFredrik Modeen		break;
5256c333678SFredrik Modeen
5266c333678SFredrik Modeen		case ADD_HOTKEY_ITEM:
5276c333678SFredrik Modeen			_AddNewSpec(NULL);
5286c333678SFredrik Modeen		break;
5296c333678SFredrik Modeen
5306c333678SFredrik Modeen		case REMOVE_HOTKEY_ITEM:
5316c333678SFredrik Modeen		{
5326c333678SFredrik Modeen			int index = fColumnListView->CurrentSelection();
5336c333678SFredrik Modeen			if (index >= 0) {
5346c333678SFredrik Modeen				CLVListItem* item = (CLVListItem*)
5356c333678SFredrik Modeen					fColumnListView->ItemAt(index);
5366c333678SFredrik Modeen				fColumnListView->RemoveItem(index);
5376c333678SFredrik Modeen				delete item;
5386c333678SFredrik Modeen				_MarkKeySetModified();
5396c333678SFredrik Modeen
5406c333678SFredrik Modeen				// Rules for new selection: If there is an item at (index),
5416c333678SFredrik Modeen				// select it. Otherwise, if there is an item at (index-1),
5426c333678SFredrik Modeen				// select it. Otherwise, select nothing.
5436c333678SFredrik Modeen				int num = fColumnListView->CountItems();
5446c333678SFredrik Modeen				if (num > 0) {
5456c333678SFredrik Modeen					if (index < num)
5466c333678SFredrik Modeen						fColumnListView->Select(index);
5476c333678SFredrik Modeen					else {
5486c333678SFredrik Modeen						if (index > 0)
5496c333678SFredrik Modeen							index--;
5506c333678SFredrik Modeen						if (index < num)
5516c333678SFredrik Modeen							fColumnListView->Select(index);
5526c333678SFredrik Modeen					}
5536c333678SFredrik Modeen				}
5546c333678SFredrik Modeen			}
5556c333678SFredrik Modeen		}
5566c333678SFredrik Modeen		break;
5576c333678SFredrik Modeen
5586c333678SFredrik Modeen		// Received when the user clicks on the ColumnListView
5596c333678SFredrik Modeen		case HOTKEY_ITEM_SELECTED:
5606c333678SFredrik Modeen		{
5616c333678SFredrik Modeen			int32 index = -1;
5626c333678SFredrik Modeen			msg->FindInt32("index", &index);
5636c333678SFredrik Modeen			bool validItem = (index >= 0);
5646c333678SFredrik Modeen			fRemoveButton->SetEnabled(validItem);
5656c333678SFredrik Modeen		}
5666c333678SFredrik Modeen		break;
5676c333678SFredrik Modeen
5686c333678SFredrik Modeen		// Received when an entry is to be modified in response to GUI activity
5696c333678SFredrik Modeen		case HOTKEY_ITEM_MODIFIED:
5706c333678SFredrik Modeen		{
5716c333678SFredrik Modeen			int32 row, column;
5726c333678SFredrik Modeen
5736c333678SFredrik Modeen			if ((msg->FindInt32("row", &row) == B_NO_ERROR)
5746c333678SFredrik Modeen				&& (msg->FindInt32("column", &column) == B_NO_ERROR)) {
5756c333678SFredrik Modeen				int32 key;
5766c333678SFredrik Modeen				const char* bytes;
5776c333678SFredrik Modeen
5786c333678SFredrik Modeen				if (row >= 0) {
5796c333678SFredrik Modeen					ShortcutsSpec* item = (ShortcutsSpec*)
5806c333678SFredrik Modeen						fColumnListView->ItemAt(row);
5816c333678SFredrik Modeen					bool repaintNeeded = false; // default
5826c333678SFredrik Modeen
5836c333678SFredrik Modeen					if (msg->HasInt32("mouseClick")) {
5846c333678SFredrik Modeen						repaintNeeded = item->ProcessColumnMouseClick(column);
5856c333678SFredrik Modeen					} else if ((msg->FindString("bytes", &bytes) == B_NO_ERROR)
5866c333678SFredrik Modeen						&& (msg->FindInt32("key", &key) == B_NO_ERROR)) {
5876c333678SFredrik Modeen						repaintNeeded = item->ProcessColumnKeyStroke(column,
5886c333678SFredrik Modeen							bytes, key);
5896c333678SFredrik Modeen					} else if (msg->FindInt32("unmappedkey", &key) ==
5906c333678SFredrik Modeen						B_NO_ERROR) {
5916c333678SFredrik Modeen						repaintNeeded = ((column == item->KEY_COLUMN_INDEX)
5926c333678SFredrik Modeen							&& ((key > 0xFF) || (GetKeyName(key) != NULL))
5936c333678SFredrik Modeen							&& (item->ProcessColumnKeyStroke(column, NULL,
5946c333678SFredrik Modeen							key)));
5956c333678SFredrik Modeen					} else if (msg->FindString("text", &bytes) == B_NO_ERROR) {
5966c333678SFredrik Modeen						if ((bytes[0] == '(')&&(bytes[1] == 'C')) {
5976c333678SFredrik Modeen							if (fSelectPanel)
5986c333678SFredrik Modeen								fSelectPanel->Show();
5996c333678SFredrik Modeen							else {
6006c333678SFredrik Modeen								BMessage msg(SELECT_APPLICATION);
6016c333678SFredrik Modeen								BMessenger m(this);
6026c333678SFredrik Modeen								fSelectPanel = new BFilePanel(B_OPEN_PANEL, &m,
6036c333678SFredrik Modeen									NULL, 0, false, &msg);
6046c333678SFredrik Modeen								fSelectPanel->Show();
6056c333678SFredrik Modeen							}
6066c333678SFredrik Modeen							fSelectPanel->SetButtonLabel(B_DEFAULT_BUTTON,
6076c333678SFredrik Modeen								"Select");
6086c333678SFredrik Modeen						} else
6096c333678SFredrik Modeen							repaintNeeded = item->ProcessColumnTextString(
6106c333678SFredrik Modeen								column, bytes);
6116c333678SFredrik Modeen					}
6126c333678SFredrik Modeen
6136c333678SFredrik Modeen					if (repaintNeeded) {
6146c333678SFredrik Modeen						fColumnListView->InvalidateItem(row);
6156c333678SFredrik Modeen						_MarkKeySetModified();
6166c333678SFredrik Modeen					}
6176c333678SFredrik Modeen				}
6186c333678SFredrik Modeen			}
6196c333678SFredrik Modeen		}
6206c333678SFredrik Modeen		break;
6216c333678SFredrik Modeen
6226c333678SFredrik Modeen		default:
6236c333678SFredrik Modeen			BWindow::MessageReceived(msg);
6246c333678SFredrik Modeen		break;
6256c333678SFredrik Modeen	}
6266c333678SFredrik Modeen}
6276c333678SFredrik Modeen
6286c333678SFredrik Modeen
6296c333678SFredrik Modeenvoid
6306c333678SFredrik ModeenShortcutsWindow::_MarkKeySetModified()
6316c333678SFredrik Modeen{
6326c333678SFredrik Modeen	if (fKeySetModified == false) {
6336c333678SFredrik Modeen		fKeySetModified = true;
6346c333678SFredrik Modeen		fSaveButton->SetEnabled(true);
6356c333678SFredrik Modeen	}
6366c333678SFredrik Modeen}
6376c333678SFredrik Modeen
6386c333678SFredrik Modeen
6396c333678SFredrik Modeenvoid
6406c333678SFredrik ModeenShortcutsWindow::Quit()
6416c333678SFredrik Modeen{
6426c333678SFredrik Modeen	for (int i = fColumnListView->CountItems() - 1; i >= 0; i--)
6436c333678SFredrik Modeen		delete (ShortcutsSpec*)fColumnListView->ItemAt(i);
6446c333678SFredrik Modeen
6456c333678SFredrik Modeen	fColumnListView->MakeEmpty();
6466c333678SFredrik Modeen	BWindow::Quit();
6476c333678SFredrik Modeen}
6486c333678SFredrik Modeen
6496c333678SFredrik Modeen
6506c333678SFredrik Modeenvoid
6516c333678SFredrik ModeenShortcutsWindow::FrameResized(float w, float h)
6526c333678SFredrik Modeen{
6536c333678SFredrik Modeen	fAddButton->ChangeToNewSize(w, h);
6546c333678SFredrik Modeen	fRemoveButton->ChangeToNewSize(w, h);
6556c333678SFredrik Modeen	fSaveButton->ChangeToNewSize(w, h);
6566c333678SFredrik Modeen}
6576c333678SFredrik Modeen
6586c333678SFredrik Modeen
6596c333678SFredrik Modeenvoid
6606c333678SFredrik ModeenShortcutsWindow::DispatchMessage(BMessage* msg, BHandler* handler)
6616c333678SFredrik Modeen{
6626c333678SFredrik Modeen	switch(msg->what) {
6636c333678SFredrik Modeen		case B_COPY:
6646c333678SFredrik Modeen		case B_CUT:
6656c333678SFredrik Modeen			if (be_clipboard->Lock()) {
6666c333678SFredrik Modeen				int32 row = fColumnListView->CurrentSelection();
6676c333678SFredrik Modeen				int32 column = fColumnListView->GetSelectedColumn();
6686c333678SFredrik Modeen				if ((row >= 0)
6696c333678SFredrik Modeen					&& (column == ShortcutsSpec::STRING_COLUMN_INDEX)) {
6706c333678SFredrik Modeen					ShortcutsSpec* spec = (ShortcutsSpec*)
6716c333678SFredrik Modeen						fColumnListView->ItemAt(row);
6726c333678SFredrik Modeen					if (spec) {
6736c333678SFredrik Modeen						BMessage* data = be_clipboard->Data();
6746c333678SFredrik Modeen						data->RemoveName("text/plain");
6756c333678SFredrik Modeen						data->AddData("text/plain", B_MIME_TYPE,
6766c333678SFredrik Modeen							spec->GetCellText(column),
6776c333678SFredrik Modeen							strlen(spec->GetCellText(column)));
6786c333678SFredrik Modeen						be_clipboard->Commit();
6796c333678SFredrik Modeen
6806c333678SFredrik Modeen						if (msg->what == B_CUT) {
6816c333678SFredrik Modeen							spec->ProcessColumnTextString(column, "");
6826c333678SFredrik Modeen							_MarkKeySetModified();
6836c333678SFredrik Modeen							fColumnListView->InvalidateItem(row);
6846c333678SFredrik Modeen						}
6856c333678SFredrik Modeen					}
6866c333678SFredrik Modeen				}
6876c333678SFredrik Modeen				be_clipboard->Unlock();
6886c333678SFredrik Modeen			}
6896c333678SFredrik Modeen		break;
6906c333678SFredrik Modeen
6916c333678SFredrik Modeen		case B_PASTE:
6926c333678SFredrik Modeen			if (be_clipboard->Lock()) {
6936c333678SFredrik Modeen				BMessage* data = be_clipboard->Data();
6946c333678SFredrik Modeen				const char* text;
6956c333678SFredrik Modeen				ssize_t textLen;
6966c333678SFredrik Modeen				if (data->FindData("text/plain", B_MIME_TYPE, (const void**)
6976c333678SFredrik Modeen					&text, &textLen) == B_NO_ERROR) {
6986c333678SFredrik Modeen					int32 row = fColumnListView->CurrentSelection();
6996c333678SFredrik Modeen					int32 column = fColumnListView->GetSelectedColumn();
7006c333678SFredrik Modeen					if ((row >= 0)
7016c333678SFredrik Modeen						&& (column == ShortcutsSpec::STRING_COLUMN_INDEX)) {
7026c333678SFredrik Modeen						ShortcutsSpec* spec = (ShortcutsSpec*)
7036c333678SFredrik Modeen							fColumnListView->ItemAt(row);
7046c333678SFredrik Modeen						if (spec) {
7056c333678SFredrik Modeen							for (ssize_t i = 0; i < textLen; i++) {
7066c333678SFredrik Modeen								char buf[2] = {text[i], 0x00};
7076c333678SFredrik Modeen								spec->ProcessColumnKeyStroke(column, buf, 0);
7086c333678SFredrik Modeen							}
7096c333678SFredrik Modeen						}
7106c333678SFredrik Modeen						fColumnListView->InvalidateItem(row);
7116c333678SFredrik Modeen						_MarkKeySetModified();
7126c333678SFredrik Modeen					}
7136c333678SFredrik Modeen				}
7146c333678SFredrik Modeen				be_clipboard->Unlock();
7156c333678SFredrik Modeen			}
7166c333678SFredrik Modeen		break;
7176c333678SFredrik Modeen
7186c333678SFredrik Modeen		default:
7196c333678SFredrik Modeen			BWindow::DispatchMessage(msg, handler);
7206c333678SFredrik Modeen		break;
7216c333678SFredrik Modeen	}
7226c333678SFredrik Modeen}
723fa1ee6d4SJonas Sundström
724