Ticket #7964: Keymap_add_Apple_Aluminum_submenu_3.diff

File Keymap_add_Apple_Aluminum_submenu_3.diff, 7.1 KB (added by jscipione, 8 years ago)

Adds the ability to turn subdirectories in the KeyboardLayouts/ directories into submenus in the Layout menu of the Keymap preference app. This patch uses recursive methods removing the limitation of only handling 1 level of subdirs. The code is much cleaner than the _2 version. No goto required. I had to remove the const qualifier on the _SaveSettings() menu to allow it to call a recursive method to find the path of the marked layout. This patch is different than versions 1 and 2 in that it only deals with turning subdirs into submenus and doesn't include the Apple Aluminum layout files or the changes to HaikuImage.

  • src/preferences/keymap/KeymapWindow.cpp

    diff --git src/preferences/keymap/KeymapWindow.cpp src/preferences/keymap/KeymapWindow.cpp
    index 62924a2..daa368c 100644
    BMenuBar*  
    375375KeymapWindow::_CreateMenu()
    376376{
    377377    BMenuBar* menuBar = new BMenuBar(Bounds(), "menubar");
    378     BMenuItem* item;
    379378
    380379    // Create the File menu
    381380    BMenu* menu = new BMenu(B_TRANSLATE("File"));
    KeymapWindow::_CreateMenu()  
    391390
    392391    // Create keyboard layout menu
    393392    fLayoutMenu = new BMenu(B_TRANSLATE("Layout"));
    394     fLayoutMenu->SetRadioMode(true);
    395     fLayoutMenu->AddItem(item = new BMenuItem(
    396         fKeyboardLayoutView->GetKeyboardLayout()->Name(),
    397         new BMessage(kChangeKeyboardLayout)));
    398     item->SetMarked(true);
    399 
    400393    _AddKeyboardLayouts(fLayoutMenu);
    401394    menuBar->AddItem(fLayoutMenu);
    402395
    KeymapWindow::_AddKeyboardLayouts(BMenu* menu)  
    531524        path.Append("KeyboardLayouts");
    532525
    533526        BDirectory directory;
    534         if (directory.SetTo(path.Path()) == B_OK) {
    535             entry_ref ref;
    536             while (directory.GetNextRef(&ref) == B_OK) {
    537                 if (menu->FindItem(ref.name) != NULL)
    538                     continue;
     527        if (directory.SetTo(path.Path()) == B_OK)
     528            _AddKeyboardLayoutMenu(menu, directory);
     529    }
     530}
    539531
    540                 BMessage* message = new BMessage(kChangeKeyboardLayout);
    541                 message->AddRef("ref", &ref);
    542532
    543                 menu->AddItem(new BMenuItem(ref.name, message));
    544             }
     533/*! Adds a menu populated with the keyboard layouts found in the passed
     534    in directory to the passed in menu. Each subdirectory in the passed
     535    in directory is added as a submenu recursively.
     536*/
     537void
     538KeymapWindow::_AddKeyboardLayoutMenu(BMenu* menu, BDirectory directory)
     539{
     540    entry_ref ref;
     541
     542    while (directory.GetNextRef(&ref) == B_OK) {
     543        if (menu->FindItem(ref.name) != NULL)
     544            continue;
     545
     546        BDirectory subdirectory;
     547        subdirectory.SetTo(&ref);
     548        if (subdirectory.InitCheck() == B_OK) {
     549            BMenu* submenu = new BMenu(ref.name);
     550
     551            _AddKeyboardLayoutMenu(submenu, subdirectory);
     552            menu->AddItem(submenu);
     553        } else {
     554            BMessage* message = new BMessage(kChangeKeyboardLayout);
     555
     556            message->AddRef("ref", &ref);
     557            menu->AddItem(new BMenuItem(ref.name, message));
    545558        }
    546559    }
    547560}
    548561
    549562
     563/*! Sets the keyboard layout with the passed in path and marks the
     564    corresponding menu item. If the path is not found in the menu this method
     565    sets the default keyboard layout and marks the corresponding menu item.
     566*/
    550567status_t
    551568KeymapWindow::_SetKeyboardLayout(const char* path)
    552569{
    553     status_t status = B_OK;
     570    status_t status = fKeyboardLayoutView->GetKeyboardLayout()->Load(path);
    554571
    555     if (path != NULL && path[0] != '\0') {
    556         status = fKeyboardLayoutView->GetKeyboardLayout()->Load(path);
    557         if (status == B_OK) {
    558             // select item
    559             for (int32 i = fLayoutMenu->CountItems(); i-- > 0;) {
    560                 BMenuItem* item = fLayoutMenu->ItemAt(i);
    561                 BMessage* message = item->Message();
    562                 entry_ref ref;
    563                 if (message->FindRef("ref", &ref) == B_OK) {
    564                     BPath layoutPath(&ref);
    565                     if (layoutPath == path) {
    566                         item->SetMarked(true);
    567                         break;
    568                     }
    569                 }
    570             }
    571         }
    572     }
     572    // mark a menu item (unmarking all others)
     573    _MarkKeyboardLayoutItem(path, fLayoutMenu);
    573574
    574     if (path == NULL || status != B_OK) {
     575    if (path == NULL || path[0] == '\0' || status != B_OK) {
    575576        fKeyboardLayoutView->GetKeyboardLayout()->SetDefault();
    576         fLayoutMenu->ItemAt(0)->SetMarked(true);
     577        BMenuItem* item = fLayoutMenu->FindItem(
     578            fKeyboardLayoutView->GetKeyboardLayout()->Name());
     579        if (item != NULL)
     580            item->SetMarked(true);
    577581    }
    578582
    579583    // Refresh currently set layout
    KeymapWindow::_SetKeyboardLayout(const char* path)  
    584588}
    585589
    586590
     591/*! Marks a keyboard layout item by iterating through the menus recursively
     592    searching for the menu item with the passed in path. This method always
     593    iterates through all menu items and unmarks them. If no item with the
     594    passed in path is found it is up to the caller to set the default keyboard
     595    layout and mark item corresponding to the default keyboard layout path.
     596*/
     597void
     598KeymapWindow::_MarkKeyboardLayoutItem(const char* path, BMenu* menu)
     599{
     600    BMenuItem* item = NULL;
     601    entry_ref ref;
     602
     603    for (int32 i = 0; i < menu->CountItems(); i++) {
     604        item = menu->ItemAt(i);
     605        if (item == NULL)
     606            continue;
     607
     608        // Unmark each item initially
     609        item->SetMarked(false);
     610
     611        BMenu* submenu = item->Submenu();
     612        if (submenu != NULL)
     613            _MarkKeyboardLayoutItem(path, submenu);
     614        else {
     615            if (item->Message()->FindRef("ref", &ref) == B_OK) {
     616                BPath layoutPath(&ref);
     617                if (path != NULL && path[0] != '\0' && layoutPath == path) {
     618                    // Found it, mark the item
     619                    item->SetMarked(true);
     620                }
     621            }
     622        }
     623    }
     624}
     625
     626
    587627/*! Sets the label of the "Switch Shorcuts" button to make it more
    588628    descriptive what will happen when you press that button.
    589629*/
    KeymapWindow::_LoadSettings(BRect& windowFrame, BString& keyboardLayout)  
    922962
    923963
    924964status_t
    925 KeymapWindow::_SaveSettings() const
     965KeymapWindow::_SaveSettings()
    926966{
    927967    BFile file;
    928968    status_t status
    KeymapWindow::_SaveSettings() const  
    933973    BMessage settings('keym');
    934974    settings.AddRect("window frame", Frame());
    935975
    936     BMenuItem* item = fLayoutMenu->FindMarked();
     976    BPath path = _GetMarkedKeyboardLayoutPath(fLayoutMenu);
     977    if (path.InitCheck() == B_OK)
     978        settings.AddString("keyboard layout", path.Path());
     979
     980    return settings.Flatten(&file);
     981}
     982
     983
     984/*! Gets the path of the currently marked keyboard layout item
     985    by searching through each of the menus recursively until
     986    a marked item is found.
     987*/
     988BPath
     989KeymapWindow::_GetMarkedKeyboardLayoutPath(BMenu* menu)
     990{
     991    BPath path;
     992    BMenuItem* item = NULL;
    937993    entry_ref ref;
    938     if (item != NULL && item->Message()->FindRef("ref", &ref) == B_OK) {
    939         BPath path(&ref);
    940         if (path.InitCheck() == B_OK)
    941             settings.AddString("keyboard layout", path.Path());
     994
     995    for (int32 i = 0; i < menu->CountItems(); i++) {
     996        item = menu->ItemAt(i);
     997        if (item == NULL)
     998            continue;
     999
     1000        BMenu* submenu = item->Submenu();
     1001        if (submenu != NULL)
     1002            return _GetMarkedKeyboardLayoutPath(submenu);
     1003        else {
     1004            if (item->IsMarked()
     1005                && item->Message()->FindRef("ref", &ref) == B_OK) {
     1006                path.SetTo(&ref);
     1007                return path;
     1008            }
     1009        }
    9421010    }
    9431011
    944     return settings.Flatten(&file);
     1012    return path;
    9451013}
  • src/preferences/keymap/KeymapWindow.h

    diff --git src/preferences/keymap/KeymapWindow.h src/preferences/keymap/KeymapWindow.h
    index cc6cb4b..acb0305 100644
    protected:  
    4040            BMenuBar*           _CreateMenu();
    4141            BView*              _CreateMapLists();
    4242            void                _AddKeyboardLayouts(BMenu* menu);
     43            void                _AddKeyboardLayoutMenu(BMenu* menu,
     44                                    BDirectory directory);
    4345            status_t            _SetKeyboardLayout(const char* path);
     46            void                _MarkKeyboardLayoutItem(const char* path,
     47                                    BMenu* menu);
    4448
    4549            void                _UpdateSwitchShortcutButton();
    4650            void                _UpdateButtons();
    protected:  
    6468            status_t            _GetSettings(BFile& file, int mode) const;
    6569            status_t            _LoadSettings(BRect& frame,
    6670                                    BString& keyboardLayout);
    67             status_t            _SaveSettings() const;
     71            status_t            _SaveSettings();
     72            BPath               _GetMarkedKeyboardLayoutPath(BMenu* menu);
    6873
    6974private:
    7075            BListView*          fSystemListView;