Ticket #5420: Shortcuts-HIG-Update-Rev2.patch

File Shortcuts-HIG-Update-Rev2.patch, 17.4 KB (added by brianluft, 13 years ago)

Revision 2 of the proposed HIG compliance patch

  • src/preferences/shortcuts/ResizableButton.h

     
    1 /*
    2  * Copyright 1999-2009 Haiku Inc. All rights reserved.
    3  * Distributed under the terms of the MIT License.
    4  *
    5  * Authors:
    6  *      Jeremy Friesner
    7  */
    8 #ifndef ResizableButton_h
    9 #define ResizableButton_h
    10 
    11 
    12 #include <Button.h>
    13 
    14 
    15 class ResizableButton : public BButton {
    16 public:
    17                             ResizableButton(BRect parentFrame, BRect frame,
    18                                 const char* name, const char* label,
    19                                 BMessage* message);
    20 
    21     virtual void            ChangeToNewSize(float newWidth, float newHeight);
    22 private:
    23             BRect           fPercentages;
    24 };
    25 
    26 
    27 #endif
    28 
  • src/preferences/shortcuts/Jamfile

     
    66Preference Shortcuts :
    77    main.cpp
    88    MetaKeyStateMap.cpp
    9     ResizableButton.cpp
    109    ShortcutsApp.cpp
    1110    ShortcutsSpec.cpp
    1211    ShortcutsWindow.cpp
  • src/preferences/shortcuts/ShortcutsWindow.cpp

     
    1515
    1616#include <Alert.h>
    1717#include <Application.h>
     18#include <Button.h>
    1819#include <Catalog.h>
    1920#include <Clipboard.h>
     21#include <ControlLook.h>
    2022#include <File.h>
     23#include <FilePanel.h>
    2124#include <FindDirectory.h>
    2225#include <Input.h>
    2326#include <Locale.h>
     27#include <Message.h>
    2428#include <Menu.h>
    2529#include <MenuBar.h>
    2630#include <MenuItem.h>
    2731#include <MessageFilter.h>
    2832#include <Path.h>
    2933#include <PopUpMenu.h>
     34#include <Screen.h>
    3035#include <ScrollBar.h>
    3136#include <ScrollView.h>
    3237#include <String.h>
     38#include <SupportDefs.h>
    3339
    3440#include "ColumnListView.h"
    3541
     
    4147
    4248
    4349// Window sizing constraints
    44 #define MIN_WIDTH   600
    45 #define MIN_HEIGHT  130
    46 #define MAX_WIDTH   65535
    47 #define MAX_HEIGHT  65535
     50#define MAX_WIDTH 10000
     51#define MAX_HEIGHT 10000
     52    // SetSizeLimits does not provide a mechanism for specifying an
     53    // unrestricted maximum.  10,000 seems to be the most common value used
     54    // in other Haiku system applications.
    4855
    49 // Default window position
    50 #define WINDOW_START_X 30
    51 #define WINDOW_START_Y 100
     56#define WINDOW_SETTINGS_FILE_NAME "Shortcuts_window_settings"
     57    // Because the "shortcuts_settings" file (SHORTCUTS_SETTING_FILE_NAME) is
     58    // already used as a communications method between this configurator and
     59    // the "shortcut_catcher" input_server filter, it should not be overloaded
     60    // with window position information.  Instead, a separate file is used.
    5261
    5362#undef B_TRANSLATE_CONTEXT
    5463#define B_TRANSLATE_CONTEXT "ShortcutsWindow"
     
    5665#define ERROR "Shortcuts error"
    5766#define WARNING "Shortcuts warning"
    5867
    59 // Global constants for Shortcuts
    60 #define V_SPACING 5 // vertical spacing between GUI components
    6168
    62 
    6369// Creates a pop-up-menu that reflects the possible states of the specified
    6470// meta-key.
    6571static BPopUpMenu*
     
    94100
    95101ShortcutsWindow::ShortcutsWindow()
    96102    :
    97     BWindow(BRect(WINDOW_START_X, WINDOW_START_Y, WINDOW_START_X + MIN_WIDTH,
    98         WINDOW_START_Y + MIN_HEIGHT * 2), B_TRANSLATE_SYSTEM_NAME("Shortcuts"),
    99         B_DOCUMENT_WINDOW, 0L),
     103    BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_SYSTEM_NAME("Shortcuts"),
     104        B_TITLED_WINDOW, 0L),
    100105    fSavePanel(NULL),
    101106    fOpenPanel(NULL),
    102107    fSelectPanel(NULL),
     
    104109    fLastOpenWasAppend(false)
    105110{
    106111    ShortcutsSpec::InitializeMetaMaps();
     112   
     113    float spacing = be_control_look->DefaultItemSpacing();
    107114
    108     SetSizeLimits(MIN_WIDTH, MAX_WIDTH, MIN_HEIGHT, MAX_HEIGHT);
     115    BView* top = new BView(Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0);
     116    top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
     117    AddChild(top);
     118
    109119    BMenuBar* menuBar = new BMenuBar(BRect(0, 0, 0, 0), "Menu Bar");
    110120
    111121    BMenu* fileMenu = new BMenu(B_TRANSLATE("File"));
    112     fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Open KeySet" B_UTF8_ELLIPSIS), 
     122    fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Open KeySet" B_UTF8_ELLIPSIS),
    113123        new BMessage(OPEN_KEYSET), 'O'));
    114124    fileMenu->AddItem(new BMenuItem(
    115         B_TRANSLATE("Append KeySet" B_UTF8_ELLIPSIS), 
     125        B_TRANSLATE("Append KeySet" B_UTF8_ELLIPSIS),
    116126        new BMessage(APPEND_KEYSET), 'A'));
    117     fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Revert to saved"), 
     127    fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Revert to saved"),
    118128        new BMessage(REVERT_KEYSET), 'A'));
    119129    fileMenu->AddItem(new BSeparatorItem);
    120130    fileMenu->AddItem(new BMenuItem(
    121         B_TRANSLATE("Save KeySet as" B_UTF8_ELLIPSIS), 
     131        B_TRANSLATE("Save KeySet as" B_UTF8_ELLIPSIS),
    122132        new BMessage(SAVE_KEYSET_AS), 'S'));
    123133    fileMenu->AddItem(new BSeparatorItem);
    124134    fileMenu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
    125135        new BMessage(B_QUIT_REQUESTED), 'Q'));
    126136    menuBar->AddItem(fileMenu);
    127137
    128     AddChild(menuBar);
     138    top->AddChild(menuBar);
    129139
    130     font_height fh;
    131     be_plain_font->GetHeight(&fh);
    132     float vButtonHeight = ceil(fh.ascent) + ceil(fh.descent) + 5.0f;
    133 
    134140    BRect tableBounds = Bounds();
    135141    tableBounds.top = menuBar->Bounds().bottom + 1;
    136142    tableBounds.right -= B_V_SCROLL_BAR_WIDTH;
    137     tableBounds.bottom -= (B_H_SCROLL_BAR_HEIGHT + V_SPACING + vButtonHeight +
    138         V_SPACING * 2);
    139    
     143    tableBounds.bottom -= B_H_SCROLL_BAR_HEIGHT;
     144
    140145    BScrollView* containerView;
    141     fColumnListView = new ColumnListView(tableBounds, &containerView, NULL, 
    142         B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE, 
     146    fColumnListView = new ColumnListView(tableBounds, &containerView, NULL,
     147        B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
    143148        B_SINGLE_SELECTION_LIST, true, true, true, B_NO_BORDER);
    144    
    145     fColumnListView->SetEditMessage(new BMessage(HOTKEY_ITEM_MODIFIED), 
     149
     150    fColumnListView->SetEditMessage(new BMessage(HOTKEY_ITEM_MODIFIED),
    146151        BMessenger(this));
    147    
    148     const float metaWidth = 50.0f;
    149152
     153    float minListWidth = 0;
     154        // A running total is kept as the columns are created.
     155    float cellWidth = be_plain_font->StringWidth("Either") + 20;
     156        // ShortcutsSpec does not seem to translate the string "Either".
     157
    150158    for (int i = 0; i < ShortcutsSpec::NUM_META_COLUMNS; i++) {
     159        const char* name = ShortcutsSpec::GetColumnName(i);
     160        float headerWidth = be_plain_font->StringWidth(name) + 20;
     161        float width = max_c(headerWidth, cellWidth);
     162        minListWidth += width + 1;
     163
    151164        fColumnListView->AddColumn(
    152             new CLVColumn(ShortcutsSpec::GetColumnName(i), CreateMetaPopUp(i),
    153             metaWidth, CLV_SORT_KEYABLE));
     165            new CLVColumn(name, CreateMetaPopUp(i), width, CLV_SORT_KEYABLE));
    154166    }
    155167
     168    float keyCellWidth = be_plain_font->StringWidth("Caps Lock") + 20;
    156169    fColumnListView->AddColumn(new CLVColumn(B_TRANSLATE("Key"),
    157         CreateKeysPopUp(), 60, CLV_SORT_KEYABLE));
     170        CreateKeysPopUp(), keyCellWidth, CLV_SORT_KEYABLE));
     171    minListWidth += keyCellWidth + 1;
    158172
    159173    BPopUpMenu* popup = new BPopUpMenu(NULL, false);
    160174    popup->AddItem(new BMenuItem(
     
    177191    popup->AddItem(new BMenuItem(B_TRANSLATE("*Beep"), NULL));
    178192    fColumnListView->AddColumn(new CLVColumn(B_TRANSLATE("Application"), popup,
    179193        323.0, CLV_SORT_KEYABLE));
     194    minListWidth += 323.0 + 1;
     195    minListWidth += B_V_SCROLL_BAR_WIDTH;
    180196
    181197    fColumnListView->SetSortFunction(ShortcutsSpec::MyCompare);
    182     AddChild(containerView);
     198    top->AddChild(containerView);
    183199
    184200    fColumnListView->SetSelectionMessage(new BMessage(HOTKEY_ITEM_SELECTED));
    185201    fColumnListView->SetTarget(this);
    186202
    187     BRect buttonBounds = Bounds();
    188     buttonBounds.left += V_SPACING;
    189     buttonBounds.right = ((buttonBounds.right - buttonBounds.left) / 2.0f)
    190         + buttonBounds.left;
    191     buttonBounds.bottom -= V_SPACING * 2;
    192     buttonBounds.top = buttonBounds.bottom - vButtonHeight;
    193     buttonBounds.right -= B_V_SCROLL_BAR_WIDTH;
    194     float origRight = buttonBounds.right;
    195     buttonBounds.right = (buttonBounds.left + origRight) * 0.40f -
    196         (V_SPACING / 2);
    197     AddChild(fAddButton = new ResizableButton(Bounds(), buttonBounds, "add",
    198         B_TRANSLATE("Add new shortcut"), new BMessage(ADD_HOTKEY_ITEM)));
    199     buttonBounds.left = buttonBounds.right + V_SPACING;
    200     buttonBounds.right = origRight;
    201     AddChild(fRemoveButton = new ResizableButton(Bounds(), buttonBounds,
    202         "remove", B_TRANSLATE("Remove selected shortcut"),
    203         new BMessage(REMOVE_HOTKEY_ITEM)));
    204    
     203    fAddButton = new BButton(BRect(0, 0, 0, 0), "add",
     204        B_TRANSLATE("Add new shortcut"), new BMessage(ADD_HOTKEY_ITEM),
     205        B_FOLLOW_BOTTOM);
     206    fAddButton->ResizeToPreferred();
     207    fAddButton->MoveBy(spacing,
     208        Bounds().bottom - fAddButton->Bounds().bottom - spacing);
     209    top->AddChild(fAddButton);
     210
     211    fRemoveButton = new BButton(BRect(0, 0, 0, 0), "remove",
     212        B_TRANSLATE("Remove selected shortcut"),
     213        new BMessage(REMOVE_HOTKEY_ITEM), B_FOLLOW_BOTTOM);
     214    fRemoveButton->ResizeToPreferred();
     215    fRemoveButton->MoveBy(fAddButton->Frame().right + spacing,
     216        Bounds().bottom - fRemoveButton->Bounds().bottom - spacing);
     217    top->AddChild(fRemoveButton);
     218
    205219    fRemoveButton->SetEnabled(false);
    206220
    207     float offset = (buttonBounds.right - buttonBounds.left) / 2.0f;
    208     BRect saveButtonBounds = buttonBounds;
    209     saveButtonBounds.right = Bounds().right - B_V_SCROLL_BAR_WIDTH - offset;
    210     saveButtonBounds.left = buttonBounds.right + V_SPACING + offset;
    211     AddChild(fSaveButton = new ResizableButton(Bounds(), saveButtonBounds,
    212         "save", B_TRANSLATE("Save & apply"), new BMessage(SAVE_KEYSET)));
    213    
     221    fSaveButton = new BButton(BRect(0, 0, 0, 0), "save",
     222        B_TRANSLATE("Save & apply"), new BMessage(SAVE_KEYSET),
     223        B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT);
     224    fSaveButton->ResizeToPreferred();
     225    fSaveButton->MoveBy(Bounds().right - fSaveButton->Bounds().right - spacing,
     226        Bounds().bottom - fSaveButton->Bounds().bottom - spacing);
     227    top->AddChild(fSaveButton);
     228
    214229    fSaveButton->SetEnabled(false);
    215230
    216     entry_ref ref; 
    217     if (_GetSettingsFile(&ref)) {
     231    containerView->ResizeBy(0,
     232        -(fAddButton->Bounds().bottom + 2 * spacing + 2));
     233
     234    float minButtonBarWidth = fRemoveButton->Frame().right
     235        + fSaveButton->Bounds().right + 2 * spacing;
     236    float minWidth = max_c(minListWidth, minButtonBarWidth);
     237
     238    float menuBarHeight = menuBar->Bounds().bottom;
     239    float buttonBarHeight = Bounds().bottom - containerView->Frame().bottom;
     240    float minHeight = menuBarHeight + 200 + buttonBarHeight;
     241
     242    SetSizeLimits(minWidth, MAX_WIDTH, minHeight, MAX_HEIGHT);
     243        // SetSizeLimits() will resize the window to the minimum size.
     244
     245    CenterOnScreen();
     246
     247    entry_ref windowSettingsRef;
     248    if (_GetWindowSettingsFile(&windowSettingsRef)) {
     249        // The window settings file is not accepted via B_REFS_RECEIVED; this
     250        // is a behind-the-scenes file that the user will never see or
     251        // interact with.
     252        BFile windowSettingsFile(&windowSettingsRef, B_READ_ONLY);
     253        BMessage loadMsg;
     254        if (loadMsg.Unflatten(&windowSettingsFile) == B_OK)
     255            _LoadWindowSettings(loadMsg);
     256    }
     257
     258    entry_ref keySetRef;
     259    if (_GetSettingsFile(&keySetRef)) {
    218260        BMessage msg(B_REFS_RECEIVED);
    219         msg.AddRef("refs", &ref);
     261        msg.AddRef("refs", &keySetRef);
    220262        msg.AddString("startupRef", "please");
    221         PostMessage(&msg); // Tell ourself to load this file if it exists.
     263        PostMessage(&msg);
     264            // Tell ourselves to load this file if it exists.
    222265    }
    223266    Show();
    224267}
     
    270313        }
    271314    }
    272315
    273     if (ret)
     316    if (ret) {
    274317        fColumnListView->DeselectAll();
     318
     319        // Save the window position.
     320        entry_ref ref;
     321        if (_GetWindowSettingsFile(&ref)) {
     322            BEntry entry(&ref);
     323            _SaveWindowSettings(entry);
     324        }
     325    }
     326   
    275327    return ret;
    276328}
    277329
     
    339391}
    340392
    341393
     394// Gets the filesystem location of the "Shortcuts_window_settings" file.
     395bool
     396ShortcutsWindow::_GetWindowSettingsFile(entry_ref* eref)
     397{
     398    BPath path;
     399    if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
     400        return false;
     401    else
     402        path.Append(WINDOW_SETTINGS_FILE_NAME);
     403
     404    return BEntry(path.Path(), true).GetRef(eref) == B_OK;
     405}
     406
     407
     408// Saves the application settings file to (saveEntry).  Because this is a
     409// non-essential file, errors are ignored when writing the settings.
     410void
     411ShortcutsWindow::_SaveWindowSettings(BEntry& saveEntry)
     412{
     413    BFile saveTo(&saveEntry, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
     414    if (saveTo.InitCheck() != B_OK)
     415        return;
     416
     417    BMessage saveMsg;
     418    saveMsg.AddRect("window frame", Frame());
     419
     420    for (int i = 0; i < fColumnListView->CountColumns(); i++) {
     421        CLVColumn* column = fColumnListView->ColumnAt(i);
     422        saveMsg.AddFloat("column width", column->Width());
     423    }
     424
     425    saveMsg.Flatten(&saveTo);
     426}
     427
     428
     429// Loads the application settings file from (loadMsg) and resizes the interface
     430// to match the previously saved settings.  Because this is a non-essential
     431// file, errors are ignored when loading the settings.
     432void
     433ShortcutsWindow::_LoadWindowSettings(const BMessage& loadMsg)
     434{
     435    BRect frame;
     436    if (loadMsg.FindRect("window frame", &frame) == B_OK) {
     437        // Ensure the frame does not resize below the computed minimum.
     438        float width = max_c(Bounds().right, frame.right - frame.left);
     439        float height = max_c(Bounds().bottom, frame.bottom - frame.top);
     440        ResizeTo(width, height);
     441
     442        // Ensure the frame is not placed outside of the screen.
     443        BScreen screen(this);
     444        float left = min_c(screen.Frame().right - width, frame.left);
     445        float top = min_c(screen.Frame().bottom - height, frame.top);
     446        MoveTo(left, top);
     447    }
     448
     449    for (int i = 0; i < fColumnListView->CountColumns(); i++) {
     450        CLVColumn* column = fColumnListView->ColumnAt(i);
     451        float columnWidth;
     452        if (loadMsg.FindFloat("column width", i, &columnWidth) == B_OK)
     453            column->SetWidth(max_c(column->Width(), columnWidth));
     454    }
     455}
     456
     457
    342458// Creates a new entry and adds it to the GUI. (defaultCommand) will be the
    343459// text in the entry, or NULL if no text is desired.
    344460void
     
    660776
    661777
    662778void
    663 ShortcutsWindow::FrameResized(float w, float h)
    664 {
    665     fAddButton->ChangeToNewSize(w, h);
    666     fRemoveButton->ChangeToNewSize(w, h);
    667     fSaveButton->ChangeToNewSize(w, h);
    668 }
    669 
    670 
    671 void
    672779ShortcutsWindow::DispatchMessage(BMessage* msg, BHandler* handler)
    673780{
    674781    switch(msg->what) {
  • src/preferences/shortcuts/ShortcutsSpec.cpp

     
    360360    if (text == NULL)
    361361        return;
    362362
     363    _CacheViewFont(owner);
     364        // Ensure that sViewFont is configured before using it to calculate
     365        // widths.  The lack of this call was causing the initial display of
     366        // columns to be incorrect, with a "jump" as all the columns correct
     367        // themselves upon the first column resize.
     368
    363369    float textWidth = sViewFont.StringWidth(text);
    364370    BPoint point;
    365371    rgb_color lowColor = color;
  • src/preferences/shortcuts/ShortcutsWindow.h

     
    1010
    1111
    1212#include <Entry.h>
    13 #include <FilePanel.h>
    14 #include <Message.h>
    15 #include <Point.h>
    1613#include <Window.h>
    1714
    1815#include "ColumnListView.h"
    19 #include "ResizableButton.h"
    2016
     17class BButton;
     18class BFilePanel;
     19class BMessage;
    2120
    2221// This class defines our preferences/configuration window.
    2322class ShortcutsWindow : public BWindow {
     
    2726
    2827    virtual void            DispatchMessage(BMessage* msg, BHandler* handler);
    2928    virtual void            Quit();
    30     virtual void            FrameResized(float w, float h);
    31     virtual void            MessageReceived(BMessage * msg);
     29    virtual void            MessageReceived(BMessage* msg);
    3230    virtual bool            QuitRequested();
    3331
    3432    // BMessage 'what' codes, representing commands understood by this Window.
     
    5755            void                _AddNewSpec(const char* defaultCommand);
    5856            void                _MarkKeySetModified();
    5957            bool                _LoadKeySet(const BMessage& loadMsg);
    60             bool                _SaveKeySet(BEntry & saveEntry);
     58            bool                _SaveKeySet(BEntry& saveEntry);
    6159            bool                _GetSettingsFile(entry_ref* ref);
     60            void                _LoadWindowSettings(const BMessage& loadMsg);
     61            void                _SaveWindowSettings(BEntry& saveEntry);
     62            bool                _GetWindowSettingsFile(entry_ref* ref);
    6263
    63             ResizableButton*    fAddButton;
    64             ResizableButton*    fRemoveButton;
    65             ResizableButton*    fSaveButton;
     64            BButton*            fAddButton;
     65            BButton*            fRemoveButton;
     66            BButton*            fSaveButton;
    6667            ColumnListView*     fColumnListView;
    6768            BFilePanel*         fSavePanel;     // for saving settings
    6869            BFilePanel*         fOpenPanel;     // for loading settings
  • src/preferences/shortcuts/ResizableButton.cpp

     
    1 /*
    2  * Copyright 1999-2009 Haiku Inc. All rights reserved.
    3  * Distributed under the terms of the MIT License.
    4  *
    5  * Authors:
    6  *      Jeremy Friesner
    7  */
    8  
    9  
    10 #include "ResizableButton.h"
    11 
    12 
    13 ResizableButton::ResizableButton(BRect parentFrame, BRect frame,
    14     const char* name, const char* label, BMessage* message)
    15     :
    16     BButton(frame, name, label, message, B_FOLLOW_BOTTOM)
    17 {
    18     float width = parentFrame.right - parentFrame.left;
    19     float height = parentFrame.bottom - parentFrame.top;
    20     fPercentages.left = frame.left / width;
    21     fPercentages.top = frame.top / height;
    22     fPercentages.right = frame.right / width;
    23     fPercentages.bottom = frame.bottom / height;
    24 }
    25  
    26 
    27 void
    28 ResizableButton::ChangeToNewSize(float newWidth, float newHeight)
    29 {
    30     float newX = fPercentages.left* newWidth;
    31     float newW = (fPercentages.right* newWidth) - newX;
    32     BRect b = Frame();
    33     MoveBy(newX - b.left, 0);
    34     ResizeTo(newW, b.bottom - b.top);
    35     Invalidate();
    36 }
    37