Exemplo n.º 1
0
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;
	}
}
Exemplo n.º 2
0
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();
}