Author: modeenf Date: 2009-10-30 22:40:49 +0100 (Fri, 30 Oct 2009) New Revision: 33848 Changeset: http://dev.haiku-os.org/changeset/33848/haiku Added: haiku/trunk/src/preferences/shortcuts/ haiku/trunk/src/preferences/shortcuts/Jamfile haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.cpp haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.h haiku/trunk/src/preferences/shortcuts/ResizableButton.cpp haiku/trunk/src/preferences/shortcuts/ResizableButton.h haiku/trunk/src/preferences/shortcuts/Shortcuts.rsrc haiku/trunk/src/preferences/shortcuts/ShortcutsApp.cpp haiku/trunk/src/preferences/shortcuts/ShortcutsApp.h haiku/trunk/src/preferences/shortcuts/ShortcutsSpec.cpp haiku/trunk/src/preferences/shortcuts/ShortcutsSpec.h haiku/trunk/src/preferences/shortcuts/ShortcutsWindow.cpp haiku/trunk/src/preferences/shortcuts/ShortcutsWindow.h haiku/trunk/src/preferences/shortcuts/clv/ haiku/trunk/src/preferences/shortcuts/clv/CLVColumn.cpp haiku/trunk/src/preferences/shortcuts/clv/CLVColumn.h haiku/trunk/src/preferences/shortcuts/clv/CLVColumnLabelView.cpp haiku/trunk/src/preferences/shortcuts/clv/CLVColumnLabelView.h haiku/trunk/src/preferences/shortcuts/clv/CLVListItem.cpp haiku/trunk/src/preferences/shortcuts/clv/CLVListItem.h haiku/trunk/src/preferences/shortcuts/clv/Colors.h haiku/trunk/src/preferences/shortcuts/clv/ColumnListView.cpp haiku/trunk/src/preferences/shortcuts/clv/ColumnListView.h haiku/trunk/src/preferences/shortcuts/clv/MouseWatcher.cpp haiku/trunk/src/preferences/shortcuts/clv/MouseWatcher.h haiku/trunk/src/preferences/shortcuts/clv/PrefilledBitmap.cpp haiku/trunk/src/preferences/shortcuts/clv/PrefilledBitmap.h haiku/trunk/src/preferences/shortcuts/clv/ScrollViewCorner.cpp haiku/trunk/src/preferences/shortcuts/clv/ScrollViewCorner.h haiku/trunk/src/preferences/shortcuts/main.cpp Modified: haiku/trunk/src/preferences/Jamfile Log: So here it goes.. I hope I have fixed all parts that don't follow our guidelines. (that python script was good start) This are the app, I havn't change the file in clv those are from Santa gift bag Modified: haiku/trunk/src/preferences/Jamfile =================================================================== --- haiku/trunk/src/preferences/Jamfile 2009-10-30 21:35:17 UTC (rev 33847) +++ haiku/trunk/src/preferences/Jamfile 2009-10-30 21:40:49 UTC (rev 33848) @@ -21,6 +21,7 @@ SubInclude HAIKU_TOP src preferences print ; SubInclude HAIKU_TOP src preferences screen ; SubInclude HAIKU_TOP src preferences screensaver ; +SubInclude HAIKU_TOP src preferences shortcuts ; SubInclude HAIKU_TOP src preferences sounds ; SubInclude HAIKU_TOP src preferences time ; SubInclude HAIKU_TOP src preferences touchpad ; Added: haiku/trunk/src/preferences/shortcuts/Jamfile =================================================================== --- haiku/trunk/src/preferences/shortcuts/Jamfile (rev 0) +++ haiku/trunk/src/preferences/shortcuts/Jamfile 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,25 @@ +SubDir HAIKU_TOP src preferences shortcuts ; + +SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src preferences shortcuts clv ] ; +SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons input_server filters shortcut_catcher ] ; + +Preference Shortcuts : + main.cpp + MetaKeyStateMap.cpp + ResizableButton.cpp + ShortcutsApp.cpp + ShortcutsSpec.cpp + ShortcutsWindow.cpp + +# clv files + CLVColumn.cpp + CLVColumnLabelView.cpp + CLVListItem.cpp + ColumnListView.cpp + MouseWatcher.cpp + PrefilledBitmap.cpp + ScrollViewCorner.cpp + + : be tracker libshortcuts_shared.a $(TARGET_LIBSTDC++) + : Shortcuts.rsrc +; Added: haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.cpp =================================================================== --- haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.cpp (rev 0) +++ haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.cpp 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,91 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + */ + + +#include "MetaKeyStateMap.h" + + +#include <stdio.h> +#include <string.h> + + +#include "BitFieldTesters.h" + + +MetaKeyStateMap::MetaKeyStateMap() + : + fKeyName(NULL) +{ + // User MUST call SetInfo() before using! +} + + +MetaKeyStateMap::MetaKeyStateMap(const char* name) +{ + SetInfo(name); +} + + +void +MetaKeyStateMap::SetInfo(const char* keyName) +{ + fKeyName = new char[strlen(keyName) + 1]; + strcpy(fKeyName, keyName); +} + + +MetaKeyStateMap::~MetaKeyStateMap() +{ + delete [] fKeyName; + int nr = fStateDescs.CountItems(); + for (int i = 0; i < nr; i++) + delete [] ((const char*) fStateDescs.ItemAt(i)); + + nr = fStateTesters.CountItems(); + for (int j = 0; j < nr; j++) + delete ((BitFieldTester*) fStateTesters.ItemAt(j)); + // _stateBits are stored in-line, no need to delete them +} + + +void +MetaKeyStateMap::AddState(const char* d, const BitFieldTester* t) +{ + char* copy = new char[strlen(d) + 1]; + strcpy(copy, d); + fStateDescs.AddItem(copy); + fStateTesters.AddItem((void *)t); +} + + +int +MetaKeyStateMap::GetNumStates() const +{ + return fStateTesters.CountItems(); +} + + +const BitFieldTester* +MetaKeyStateMap::GetNthStateTester(int stateNum) const +{ + return ((const BitFieldTester*) fStateTesters.ItemAt(stateNum)); +} + + +const char* +MetaKeyStateMap::GetNthStateDesc(int stateNum) const +{ + return ((const char*) fStateDescs.ItemAt(stateNum)); +} + + +const char* +MetaKeyStateMap::GetName() const +{ + return fKeyName; +} Added: haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.h =================================================================== --- haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.h (rev 0) +++ haiku/trunk/src/preferences/shortcuts/MetaKeyStateMap.h 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + */ + + +#ifndef MetaKeyStateMap_h +#define MetaKeyStateMap_h + +#include <SupportDefs.h> +#include <List.h> + +class BitFieldTester; + +// This class defines a set of possible chording states (e.g. "Left only", +// "Right only", "Both", "Either") for a meta-key (e.g. Shift), and the +// description strings and qualifier bit-chords that go with them. +class MetaKeyStateMap { +public: + + // Note: You MUST call SetInfo() directly after using this ctor! + MetaKeyStateMap(); + + // Creates a MetaKeyStateMap with the give name + // (e.g. "Shift" or "Ctrl") + MetaKeyStateMap(const char* keyName); + + + ~MetaKeyStateMap(); + + // For when you have to use the default ctor + void SetInfo(const char* keyName); + + // (tester) becomes property of this map! + void AddState(const char* desc, const BitFieldTester* tester); + + // Returns the name of the meta-key (e.g. "Ctrl") + const char* GetName() const; + + // Returns the number of possible states contained in this + // MetaKeyStateMap. + int GetNumStates() const; + + // Returns a BitFieldTester that tests for the nth state's + // presence. + const BitFieldTester* GetNthStateTester(int stateNum) const; + + // Returns a textual description of the nth state (e.g. "Left") + const char* GetNthStateDesc(int stateNum) const; + +private: + // e.g. "Alt" or "Ctrl" + char* fKeyName; + + // list of strings e.g. "Left" or "Both" + BList fStateDescs; + + // list of BitFieldTesters for testing bits of modifiers + // in state + BList fStateTesters; +}; + +#endif Added: haiku/trunk/src/preferences/shortcuts/ResizableButton.cpp =================================================================== --- haiku/trunk/src/preferences/shortcuts/ResizableButton.cpp (rev 0) +++ haiku/trunk/src/preferences/shortcuts/ResizableButton.cpp 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,35 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + */ + + +#include "ResizableButton.h" + +ResizableButton::ResizableButton(BRect parentFrame, BRect frame, + const char* name, const char* label, BMessage* msg) + : + BButton(frame, name, label, msg, B_FOLLOW_BOTTOM) +{ + float width = parentFrame.right - parentFrame.left; + float height = parentFrame.bottom - parentFrame.top; + fPercentages.left = frame.left / width; + fPercentages.top = frame.top / height; + fPercentages.right = frame.right / width; + fPercentages.bottom = frame.bottom / height; +} + + +void +ResizableButton::ChangeToNewSize(float newWidth, float newHeight) +{ + float newX = fPercentages.left* newWidth; + float newW = (fPercentages.right* newWidth) - newX; + BRect b = Frame(); + MoveBy(newX - b.left, 0); + ResizeTo(newW, b.bottom - b.top); + Invalidate(); +} Added: haiku/trunk/src/preferences/shortcuts/ResizableButton.h =================================================================== --- haiku/trunk/src/preferences/shortcuts/ResizableButton.h (rev 0) +++ haiku/trunk/src/preferences/shortcuts/ResizableButton.h 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,30 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + */ + + +#ifndef ResizableButton_h +#define ResizableButton_h + +#include <Message.h> +#include <Rect.h> +#include <View.h> +#include <Button.h> + +//Just like a regular BButton, but with a handy resize method added +class ResizableButton : public BButton { +public: + ResizableButton(BRect parentFrame, BRect frame, + const char* name, const char* label, + BMessage* msg); + + virtual void ChangeToNewSize(float newWidth, float newHeight); +private: + BRect fPercentages; +}; + +#endif Added: haiku/trunk/src/preferences/shortcuts/Shortcuts.rsrc =================================================================== (Binary files differ) Property changes on: haiku/trunk/src/preferences/shortcuts/Shortcuts.rsrc ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: haiku/trunk/src/preferences/shortcuts/ShortcutsApp.cpp =================================================================== --- haiku/trunk/src/preferences/shortcuts/ShortcutsApp.cpp (rev 0) +++ haiku/trunk/src/preferences/shortcuts/ShortcutsApp.cpp 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,48 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + * Fredrik Modéen + */ + +#include "ShortcutsApp.h" + + +#include "Alert.h" + + +#include "ShortcutsWindow.h" + +#define APPLICATION_SIGNATURE "application/x-vnd.ShortcutsKeys" + +ShortcutsApp::ShortcutsApp() + : + BApplication(APPLICATION_SIGNATURE) +{ +} + + +void +ShortcutsApp::ReadyToRun() +{ + ShortcutsWindow* window = new ShortcutsWindow(); + window->Show(); +} + + +ShortcutsApp::~ShortcutsApp() +{ + +} + + +void +ShortcutsApp::AboutRequested() +{ + BAlert* alert = new BAlert("About Shortcuts", + "Shortcuts v1.28(SpicyKeys v1.28)\nby Jeremy Friesner" + , "Ok"); + alert->Go(); +} Added: haiku/trunk/src/preferences/shortcuts/ShortcutsApp.h =================================================================== --- haiku/trunk/src/preferences/shortcuts/ShortcutsApp.h (rev 0) +++ haiku/trunk/src/preferences/shortcuts/ShortcutsApp.h 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,24 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + * Fredrik Modéen + */ + + +#ifndef ShortcutsApp_h +#define ShortcutsApp_h + +#include <Application.h> + +class ShortcutsApp : public BApplication { +public: + ShortcutsApp(); + ~ShortcutsApp(); + virtual void ReadyToRun(); + virtual void AboutRequested(); +}; + +#endif Added: haiku/trunk/src/preferences/shortcuts/ShortcutsSpec.cpp =================================================================== --- haiku/trunk/src/preferences/shortcuts/ShortcutsSpec.cpp (rev 0) +++ haiku/trunk/src/preferences/shortcuts/ShortcutsSpec.cpp 2009-10-30 21:40:49 UTC (rev 33848) @@ -0,0 +1,838 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + */ + + +#include "ShortcutsSpec.h" + + +#include <ctype.h> +#include <stdio.h> + +#include <Region.h> +#include <Window.h> +#include <Directory.h> +#include <Path.h> +#include <NodeInfo.h> +#include <Beep.h> + + +#include "ColumnListView.h" + + +#include "Colors.h" +#include "MetaKeyStateMap.h" +#include "BitFieldTesters.h" +#include "CommandActuators.h" +#include "ParseCommandLine.h" + +#define CLASS "ShortcutsSpec : " + +const float _height = 20.0f; + +static MetaKeyStateMap _metaMaps[ShortcutsSpec::NUM_META_COLUMNS]; +static bool _metaMapsInitialized = false; + +static bool _fontCached = false; +static BFont _viewFont; +static float _fontHeight; +static BBitmap * _actuatorBitmaps[2]; + +// These meta-keys are pretty standard +#define SHIFT_NAME "Shift" +#define CONTROL_NAME "Control" + +// These meta-keys have different names on an Intel keyboard +#if __INTEL__ + #define OPTION_NAME "Window" + #define COMMAND_NAME "Alt" +#else + #define OPTION_NAME "Option" + #define COMMAND_NAME "Command" +#endif + +#define ICON_BITMAP_RECT BRect(0.0f, 0.0f, 15.0f, 15.0f) +#define ICON_BITMAP_SPACE B_COLOR_8_BIT + +// Returns the (pos)'th char in the string, or '\0' if (pos) if off the end of +// the string +static char GetLetterAt(const char* str, int pos); + +static char +GetLetterAt(const char* str, int pos) +{ + for (int i = 0; i < pos; i++) + if (str[i] == '\0') + return '\0'; + return str[pos]; +} + + +// Setup the states in a standard manner for a pair of meta-keys. +static void +SetupStandardMap(MetaKeyStateMap& map, const char* name, uint32 both, + uint32 left, uint32 right) +{ + map.SetInfo(name); + + // In this state, neither key may be pressed. + map.AddState("(None)", new HasBitsFieldTester(0, both)); + + // Here, either may be pressed. (Remember both is NOT a 2-bit chord, it's + // another bit entirely) + map.AddState("Either", new HasBitsFieldTester(both)); + + // Here, only the left may be pressed + map.AddState("Left", new HasBitsFieldTester(left, right)); + + // Here, only the right may be pressed + map.AddState("Right", new HasBitsFieldTester(right, left)); + + // Here, both must be pressed. + map.AddState("Both", new HasBitsFieldTester(left | right)); +} + + +MetaKeyStateMap & GetNthKeyMap(int which) +{ + return _metaMaps[which]; +} + + +static BBitmap* MakeActuatorBitmap(bool lit); +static BBitmap* +MakeActuatorBitmap(bool lit) +{ + BBitmap* map = new BBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE, true); + const rgb_color yellow = {255, 255, 0}; + const rgb_color red = {200, 200, 200}; + const rgb_color black = {0, 0, 0}; + const BPoint points[10] = { + BPoint(8, 0), BPoint(9.8, 5.8), BPoint(16, 5.8), + BPoint(11, 9.0), BPoint(13, 16), BPoint(8, 11), + BPoint(3, 16), BPoint(5, 9.0), BPoint(0, 5.8), + BPoint(6.2, 5.8) }; + + BView* view = new BView(BRect(0, 0, 16, 16), NULL, B_FOLLOW_ALL_SIDES, 0L); + map->AddChild(view); + map->Lock(); + view->SetHighColor(B_TRANSPARENT_32_BIT); + view->FillRect(ICON_BITMAP_RECT); + view->SetHighColor(lit ? yellow : red); + view->FillPolygon(points, 10); + view->SetHighColor(black); + view->StrokePolygon(points, 10); + map->Unlock(); + map->RemoveChild(view); + delete view; + return map; +} + + +void InitializeMetaMaps() +{ + _metaMapsInitialized = true; + SetupStandardMap(_metaMaps[ShortcutsSpec::SHIFT_COLUMN_INDEX], SHIFT_NAME, + B_SHIFT_KEY, B_LEFT_SHIFT_KEY, B_RIGHT_SHIFT_KEY); + + SetupStandardMap(_metaMaps[ShortcutsSpec::CONTROL_COLUMN_INDEX], + CONTROL_NAME, B_CONTROL_KEY, B_LEFT_CONTROL_KEY, B_RIGHT_CONTROL_KEY); + + SetupStandardMap(_metaMaps[ShortcutsSpec::COMMAND_COLUMN_INDEX], + COMMAND_NAME, B_COMMAND_KEY, B_LEFT_COMMAND_KEY, B_RIGHT_COMMAND_KEY); + + SetupStandardMap(_metaMaps[ShortcutsSpec::OPTION_COLUMN_INDEX], OPTION_NAME + , B_OPTION_KEY, B_LEFT_OPTION_KEY, B_RIGHT_OPTION_KEY); + + _actuatorBitmaps[0] = MakeActuatorBitmap(false); + _actuatorBitmaps[1] = MakeActuatorBitmap(true); +} + + +ShortcutsSpec::ShortcutsSpec(const char* cmd) + : + CLVListItem(0, false, false, _height), + fCommand(NULL), + fTextOffset(0), + fBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE), + fLastBitmapName(NULL), + fBitmapValid(false), + fKey(0), + fCursorPtsValid(false) +{ + for (int i = 0; i < NUM_META_COLUMNS; i++) + fMetaCellStateIndex[i] = 0; + SetCommand(cmd); +} + + +ShortcutsSpec::ShortcutsSpec(const ShortcutsSpec& from) + : + CLVListItem(0, false, false, _height), + fCommand(NULL), + fTextOffset(from.fTextOffset), + fBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE), + fLastBitmapName(NULL), + fBitmapValid(false), + fKey(from.fKey), + fCursorPtsValid(false) +{ + for (int i = 0; i < NUM_META_COLUMNS; i++) + fMetaCellStateIndex[i] = from.fMetaCellStateIndex[i]; + + SetCommand(from.fCommand); + SetSelectedColumn(from.GetSelectedColumn()); +} + + +ShortcutsSpec::ShortcutsSpec(BMessage* from) + : + CLVListItem(0, false, false, _height), + fCommand(NULL), + fTextOffset(0), + fBitmap(ICON_BITMAP_RECT, ICON_BITMAP_SPACE), + fLastBitmapName(NULL), + fBitmapValid(false), + fCursorPtsValid(false) +{ + const char* temp; + if (from->FindString("command", &temp) != B_NO_ERROR) { + printf(CLASS " Error, no command string in archive BMessage!\n"); + temp = ""; + } + + SetCommand(temp); + + if (from->FindInt32("key", (int32*) &fKey) != B_NO_ERROR) + printf(CLASS " Error, no key int32 in archive BMessage!\n"); + + for (int i = 0; i < NUM_META_COLUMNS; i++) + if (from->FindInt32("mcidx", i, (int32*)&fMetaCellStateIndex[i]) + != B_NO_ERROR) + printf(CLASS " Error, no modifiers int32 in archive BMessage!\n"); +} + + +void +ShortcutsSpec::SetCommand(const char* command) +{ + delete[] fCommand; // out with the old (if any)... + fCommandLen = strlen(command) + 1; + fCommandNul = fCommandLen - 1; + fCommand = new char[fCommandLen]; + strcpy(fCommand, command); + _UpdateIconBitmap(); +} + + +const char* +ShortcutsSpec::GetColumnName(int i) +{ + return _metaMaps[i].GetName(); +} + + +status_t +ShortcutsSpec::Archive(BMessage* into, bool deep) const +{ + status_t ret = BArchivable::Archive(into, deep); + if (ret != B_NO_ERROR) + return ret; + + into->AddString("class", "ShortcutsSpec"); + + // These fields are for our prefs panel's benefit only + into->AddString("command", fCommand); + into->AddInt32("key", fKey); + + // Assemble a BitFieldTester for the input_server add-on to use... + MinMatchFieldTester test(NUM_META_COLUMNS, false); + for (int i = 0; i < NUM_META_COLUMNS; i++) { + // for easy parsing by prefs applet on load-in + into->AddInt32("mcidx", fMetaCellStateIndex[i]); + test.AddSlave(_metaMaps[i].GetNthStateTester(fMetaCellStateIndex[i])); + } + + BMessage testerMsg; + ret = test.Archive(&testerMsg); + if (ret != B_NO_ERROR) + return ret; + + into->AddMessage("modtester", &testerMsg); + + // And also create a CommandActuator for the input_server add-on to execute + CommandActuator* act = CreateCommandActuator(fCommand); + BMessage actMsg; + ret = act->Archive(&actMsg); + if (ret != B_NO_ERROR) + return ret; + delete act; + + into->AddMessage("act", &actMsg); + return ret; +} + + +static bool IsValidActuatorName(const char* c); +static bool +IsValidActuatorName(const char* c) +{ + return ((strcmp(c, "InsertString") == 0) || + (strcmp(c, "MoveMouse") == 0) || + (strcmp(c, "MoveMouseTo") == 0) || + (strcmp(c, "MouseButton") == 0) || + (strcmp(c, "LaunchHandler") == 0) || // new for v1.21 --jaf + (strcmp(c, "Multi") == 0) || // new for v1.24 --jaf + (strcmp(c, "MouseDown") == 0) || // new for v1.24 --jaf + (strcmp(c, "MouseUp") == 0) || // new for v1.24 --jaf + (strcmp(c, "SendMessage") == 0) || // new for v1.25 --jaf + (strcmp(c, "Beep") == 0)); +} + + +BArchivable* +ShortcutsSpec::Instantiate(BMessage* from) +{ + bool validateOK = false; + if (validate_instantiation(from, "ShortcutsSpec")) + validateOK = true; + else //test the old one. + if (validate_instantiation(from, "SpicyKeysSpec")) + validateOK = true; + + if (!validateOK) + return NULL; + + return new ShortcutsSpec(from); +} + + +ShortcutsSpec::~ShortcutsSpec() +{ + delete[] fCommand; + delete[] fLastBitmapName; +} + + +void +ShortcutsSpec::_CacheViewFont(BView* owner) +{ + if (_fontCached == false) { + _fontCached = true; + owner->GetFont(&_viewFont); + font_height fh; + _viewFont.GetHeight(&fh); + _fontHeight = fh.ascent - fh.descent; + } +} + + +void +ShortcutsSpec::DrawItemColumn(BView* owner, BRect item_column_rect, + int32 column_index, bool columnSelected, bool complete) +{ + const float STRING_COLUMN_LEFT_MARGIN = 25.0f; // 16 for the icon,+9 empty + + rgb_color color; + bool selected = IsSelected(); + if (selected) + color = columnSelected ? BeBackgroundGrey : BeListSelectGrey; + else + color = BeInactiveControlGrey; + owner->SetLowColor(color); + owner->SetDrawingMode(B_OP_COPY); + owner->SetHighColor(color); + owner->FillRect(item_column_rect); + + const char* text = GetCellText(column_index); + + if (text == NULL) + return; + + float textWidth = _viewFont.StringWidth(text); + BPoint point; + rgb_color lowColor = color; + + if (column_index == STRING_COLUMN_INDEX) { + // left justified + point.Set(item_column_rect.left + STRING_COLUMN_LEFT_MARGIN, + item_column_rect.top + fTextOffset); + + item_column_rect.left = point.x;//keep text from drawing into icon area + + // scroll if too wide + float rectWidth = item_column_rect.Width() - STRING_COLUMN_LEFT_MARGIN; + float extra = textWidth - rectWidth; + if (extra > 0.0f) + point.x -= extra; + } else { + if ((column_index < NUM_META_COLUMNS) && (text[0] == '(')) + return; // don't draw for this ... + + if ((column_index <= NUM_META_COLUMNS) && (text[0] == '\0')) + return; // don't draw for this ... + + // centered + point.Set((item_column_rect.left + item_column_rect.right) / 2.0, + item_column_rect.top + fTextOffset); + _CacheViewFont(owner); + point.x -= textWidth / 2.0f; + } + + BRegion Region; + Region.Include(item_column_rect); + owner->ConstrainClippingRegion(&Region); + if (column_index != STRING_COLUMN_INDEX) { + const float KEY_MARGIN = 3.0f; + const float CORNER_RADIUS = 3.0f; + _CacheViewFont(owner); + + // How about I draw a nice "key" background for this one? + BRect textRect(point.x - KEY_MARGIN, (point.y-_fontHeight) - KEY_MARGIN + , point.x + textWidth + KEY_MARGIN - 2.0f, point.y + KEY_MARGIN); + + if (column_index == KEY_COLUMN_INDEX) + lowColor = ReallyLightPurple; + else + lowColor = LightYellow; + + owner->SetHighColor(lowColor); + owner->FillRoundRect(textRect, CORNER_RADIUS, CORNER_RADIUS); + owner->SetHighColor(Black); + owner->StrokeRoundRect(textRect, CORNER_RADIUS, CORNER_RADIUS); + } + + owner->SetHighColor(Black); + owner->SetLowColor(lowColor); + owner->DrawString(text, point); + // with a cursor at the end if highlighted + if (column_index == STRING_COLUMN_INDEX) { + // Draw cursor + if ((columnSelected) && (selected)) { + point.x += textWidth; + point.y += (fTextOffset / 4.0f); + + BPoint pt2 = point; + pt2.y -= fTextOffset; + owner->StrokeLine(point, pt2); + + fCursorPt1 = point; + fCursorPt2 = pt2; + fCursorPtsValid = true; + } + + BRegion bitmapRegion; + item_column_rect.left -= (STRING_COLUMN_LEFT_MARGIN - 4.0f); + item_column_rect.right = item_column_rect.left + 16.0f; + item_column_rect.top += 3.0f; + item_column_rect.bottom = item_column_rect.top + 16.0f; + + bitmapRegion.Include(item_column_rect); + owner->ConstrainClippingRegion(&bitmapRegion); + owner->SetDrawingMode(B_OP_OVER); + + if ((fCommand != NULL) && (fCommand[0] == '*')) + owner->DrawBitmap(_actuatorBitmaps[fBitmapValid ? 1 : 0], + ICON_BITMAP_RECT, item_column_rect); + else + // Draw icon, if any + if (fBitmapValid) + owner->DrawBitmap(&fBitmap, ICON_BITMAP_RECT, + item_column_rect); + } + + owner->SetDrawingMode(B_OP_COPY); + owner->ConstrainClippingRegion(NULL); +} + + +void +ShortcutsSpec::Update(BView* owner, const BFont* font) +{ + CLVListItem::Update(owner, font); + font_height FontAttributes; + be_plain_font->GetHeight(&FontAttributes); + float fontHeight = ceil(FontAttributes.ascent) + + ceil(FontAttributes.descent); + fTextOffset = ceil(FontAttributes.ascent) + (Height() - fontHeight) / 2.0; +} + + +const char* +ShortcutsSpec::GetCellText(int whichColumn) const +{ + const char* temp = ""; // default + switch(whichColumn) + { + case KEY_COLUMN_INDEX: + { + if ((fKey > 0) && (fKey <= 0xFF)) { + temp = GetKeyName(fKey); + if (temp == NULL) + temp = ""; + } else if (fKey > 0xFF) { + sprintf(fScratch, "#%x", fKey); + return fScratch; + } + } + break; + + case STRING_COLUMN_INDEX: + temp = fCommand; + break; + + default: + if ((whichColumn >= 0) && (whichColumn < NUM_META_COLUMNS)) + temp = _metaMaps[whichColumn].GetNthStateDesc( + fMetaCellStateIndex[whichColumn]); + break; + } + return temp; +} + + +bool +ShortcutsSpec::ProcessColumnMouseClick(int whichColumn) +{ + if ((whichColumn >= 0) && (whichColumn < NUM_META_COLUMNS)) { + // same as hitting space for these columns: cycle entry + const char temp = B_SPACE; + + // 3rd arg isn't correct but it isn't read for this case anyway + return ProcessColumnKeyStroke(whichColumn, &temp, 0); + } + return false; +} + + +bool +ShortcutsSpec::ProcessColumnTextString(int whichColumn, const char* string) +{ + switch(whichColumn) { + case STRING_COLUMN_INDEX: + SetCommand(string); + return true; + break; + + case KEY_COLUMN_INDEX: + { + fKey = FindKeyCode(string); + return true; + break; + } + + default: + return ProcessColumnKeyStroke(whichColumn, string, 0); + } +} + + +bool +ShortcutsSpec::_AttemptTabCompletion() +{ + bool ret = false; + + int32 argc; + char** argv = ParseArgvFromString(fCommand, argc); + if (argc > 0) { + // Try to complete the path partially expressed in the last argument! + char* arg = argv[argc - 1]; + char* fileFragment = strrchr(arg, '/'); + if (fileFragment) { + const char* directoryName = (fileFragment == arg) ? "/" : arg; + *fileFragment = '\0'; + fileFragment++; + int fragLen = strlen(fileFragment); + + BDirectory dir(directoryName); + if (dir.InitCheck() == B_NO_ERROR) { + BEntry nextEnt; + BPath nextPath; + BList matchList; + int maxEntryLen = 0; + + // Read in all the files in the directory whose names start + // with our fragment. + while (dir.GetNextEntry(&nextEnt) == B_NO_ERROR) { + if (nextEnt.GetPath(&nextPath) == B_NO_ERROR) { + char* filePath = strrchr(nextPath.Path(), '/') + 1; + if (strncmp(filePath, fileFragment, fragLen) == 0) { + int len = strlen(filePath); + if (len > maxEntryLen) + maxEntryLen = len; + char* newStr = new char[len + 1]; + strcpy(newStr, filePath); + matchList.AddItem(newStr); + } + } + } + + // Now slowly extend our keyword to its full length, counting + // numbers of matches at each step. If the match list length + // is 1, we can use that whole entry. If it's greater than one + // , we can use just the match length. + int matchLen = matchList.CountItems(); + if (matchLen > 0) { + int i; + BString result(fileFragment); + for (i = fragLen; i < maxEntryLen; i++) { + // See if all the matching entries have the same letter + // in the next position... if so, we can go farther. + char commonLetter = '\0'; + for (int j = 0; j < matchLen; j++) { + char nextLetter = GetLetterAt( + (char*)matchList.ItemAt(j), i); + if (commonLetter == '\0') + commonLetter = nextLetter; + + if ((commonLetter != '\0') + && (commonLetter != nextLetter)) { + commonLetter = '\0';// failed; + beep(); + break; + } + } + if (commonLetter == '\0') + break; + else + result.Append(commonLetter, 1); + } + + // Free all the strings we allocated + for (int k = 0; k < matchLen; k++) + delete [] ((char*)matchList.ItemAt(k)); + + DoStandardEscapes(result); + + BString wholeLine; [... truncated: 4862 lines follow ...]