* Copyright 2014 Freeman Lou <freemanlou2430@yahoo.com>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "VirtualKeyboardWindow.h"
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <GroupLayoutBuilder.h>
#include <ListView.h>
#include <Locale.h>
#include <Menu.h>
#include <MenuItem.h>
#include <Path.h>
#include <Screen.h>
#include "KeyboardLayoutView.h"
#include "KeymapListItem.h"
static const uint32 kMsgMenuFontChange = 'mMFC';
static int
compare_key_list_items(const void* a, const void* b)
{
KeymapListItem* item1 = *(KeymapListItem**)a;
KeymapListItem* item2 = *(KeymapListItem**)b;
return BLocale::Default()->StringCompare(item1->Text(), item2->Text());
}
VirtualKeyboardWindow::VirtualKeyboardWindow(BInputServerDevice* dev)
:
BWindow(BRect(0, 0, 0, 0), "Virtual Keyboard", B_NO_BORDER_WINDOW_LOOK,
B_FLOATING_ALL_WINDOW_FEEL, B_WILL_ACCEPT_FIRST_CLICK | B_AVOID_FOCUS),
fDevice(dev)
{
BScreen screen;
BRect screenRect(screen.Frame());
ScreenChanged(screenRect, screen.ColorSpace());
SetLayout(new BGroupLayout(B_VERTICAL));
fMapListView = new BListView("Maps");
fFontMenu = new BMenu("Font");
fLayoutMenu = new BMenu("Layout");
_LoadMaps();
_LoadLayouts(fLayoutMenu);
_LoadFonts();
fCurrentKeymap.SetToCurrent();
fKeyboardView = new KeyboardLayoutView("Keyboard", fDevice);
fKeyboardView->GetKeyboardLayout()->SetDefault();
fKeyboardView->SetKeymap(&fCurrentKeymap);
AddChild(BGroupLayoutBuilder(B_VERTICAL).Add(fKeyboardView));
}
void
VirtualKeyboardWindow::_LoadLayouts(BMenu* menu)
{
directory_which dataDirectories[] = {
B_USER_NONPACKAGED_DATA_DIRECTORY,
B_USER_DATA_DIRECTORY,
B_SYSTEM_NONPACKAGED_DIRECTORY,
B_SYSTEM_DATA_DIRECTORY,
};
for (uint i = 0; i < sizeof(dataDirectories) / sizeof(directory_which); i++) {
BPath path;
if (find_directory(dataDirectories[i], &path) != B_OK)
continue;
path.Append("KeyboardLayouts");
BDirectory directory;
if (directory.SetTo(path.Path()) == B_OK)
_LoadLayoutMenu(menu, directory);
}
}
void
VirtualKeyboardWindow::_LoadLayoutMenu(BMenu* menu, BDirectory directory)
{
entry_ref ref;
while (directory.GetNextRef(&ref) == B_OK) {
if (menu->FindItem(ref.name) != NULL)
continue;
BDirectory subdirectory;
subdirectory.SetTo(&ref);
if (subdirectory.InitCheck() == B_OK) {
BMenu* submenu = new BMenu(ref.name);
_LoadLayoutMenu(submenu, subdirectory);
menu->AddItem(submenu);
} else {
menu->AddItem(new BMenuItem(ref.name, NULL));
}
}
}
void
VirtualKeyboardWindow::_LoadMaps()
{
BPath path;
if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) != B_OK)
return;
path.Append("Keymaps");
BDirectory directory;
entry_ref ref;
if (directory.SetTo(path.Path()) == B_OK) {
while (directory.GetNextRef(&ref) == B_OK) {
fMapListView->AddItem(new KeymapListItem(ref));
}
}
fMapListView->SortItems(&compare_key_list_items);
}
void
VirtualKeyboardWindow::_LoadFonts()
{
int32 numFamilies = count_font_families();
font_family family, currentFamily;
font_style currentStyle;
uint32 flags;
be_plain_font->GetFamilyAndStyle(¤tFamily, ¤tStyle);
for (int32 i = 0; i < numFamilies; i++) {
if (get_font_family(i, &family, &flags) == B_OK) {
BMenuItem* item = new BMenuItem(family, NULL);
fFontMenu->AddItem(item);
if (!strcmp(family, currentFamily))
item->SetMarked(true);
}
}
}
void
VirtualKeyboardWindow::MessageReceived(BMessage* message)
{
if (message->what == kKeymapChange) {
fCurrentKeymap.SetToCurrent();
fKeyboardView->SetKeymap(&fCurrentKeymap);
}
BWindow::MessageReceived(message);
}
void
VirtualKeyboardWindow::ScreenChanged(BRect screenRect, color_space depth)
{
ResizeTo(screenRect.Width(), screenRect.Height() / 3);
MoveTo(0, screenRect.Height() - screenRect.Height() / 3);
}