예제 #1
0
void NpcSellDialog::sellAction(const ActionEvent &event)
{
    const std::string &eventId = event.getId();
    const int selectedItem = mShopItemList->getSelected();
    ShopItem *const item = mShopItems->at(selectedItem);
    if (!item || PlayerInfo::isItemProtected(item->getId()))
        return;

    if (eventId == "presell")
    {
        if (mAmountItems <= 0 || mAmountItems > mMaxItems)
            return;

        const ItemInfo &info = ItemDB::get(item->getId());
        if (info.isProtected())
        {
            ConfirmDialog *const dialog = CREATEWIDGETR(ConfirmDialog,
                                          // TRANSLATORS: sell confirmation header
                                          _("sell item"),
                                          // TRANSLATORS: sell confirmation message
                                          strprintf(_("Do you really want to sell %s?"),
                                                    info.getName().c_str()),
                                          SOUND_REQUEST,
                                          false,
                                          Modal_true);
            dialog->addActionListener(this);
            return;
        }
    }

    if (mAdvanced)
        sellManyItems(event.getId());
    else
        sellOneItem();
}
예제 #2
0
SkillDialog::SkillDialog() :
    // TRANSLATORS: skills dialog name
    Window(_("Skills"), Modal_false, nullptr, "skills.xml"),
    ActionListener(),
    mSkills(),
    mDurations(),
    mTabs(CREATEWIDGETR(TabbedArea, this)),
    mDeleteTabs(),
    mPointsLabel(new Label(this, "0")),
    // TRANSLATORS: skills dialog button
    mUseButton(new Button(this, _("Use"), "use", this)),
    // TRANSLATORS: skills dialog button
    mIncreaseButton(new Button(this, _("Up"), "inc", this)),
    mDefaultModel(nullptr)
{
    setWindowName("Skills");
    setCloseButton(true);
    setResizable(true);
    setSaveVisible(true);
    setStickyButtonLock(true);
    setDefaultSize(windowContainer->getWidth() - 280, 30, 275, 425);
    if (setupWindow)
        setupWindow->registerWindowForReset(this);

    mUseButton->setEnabled(false);
    mIncreaseButton->setEnabled(false);

    place(0, 0, mTabs, 5, 5);
    place(0, 5, mPointsLabel, 4);
    place(3, 5, mUseButton);
    place(4, 5, mIncreaseButton);
}
예제 #3
0
void BuySellRecv::processNpcSell(Net::MessageIn &msg)
{
    msg.readInt16("len");
    const int n_items = (msg.getLength() - 4) / 10;
    if (n_items > 0)
    {
        SellDialog *const dialog = CREATEWIDGETR(NpcSellDialog, mNpcId);
        dialog->setMoney(PlayerInfo::getAttribute(Attributes::MONEY));

        for (int k = 0; k < n_items; k++)
        {
            const int index = msg.readInt16("index") - INVENTORY_OFFSET;
            const int value = msg.readInt32("value");
            msg.readInt32("value?");

            const Item *const item = PlayerInfo::getInventory()
                ->getItem(index);

            if (item && item->isEquipped() == Equipped_false)
                dialog->addItem(item, value);
        }
    }
    else
    {
        NotifyManager::notify(NotifyTypes::SELL_LIST_EMPTY);
    }
}
예제 #4
0
void BuyingStoreRecv::processBuyingStoreItemsList(Net::MessageIn &msg)
{
    const int count = (msg.readInt16("len") - 16) / 9;
    const BeingId id = msg.readBeingId("account id");
    const int storeId = msg.readInt32("store id");
    // +++ in future need use it too
    msg.readInt32("money limit");

    const Being *const dstBeing = actorManager->findBeing(id);
    if (!dstBeing)
        return;

    SellDialog *const dialog = CREATEWIDGETR(BuyingStoreSellDialog,
        dstBeing->getId(),
        storeId);
    dialog->setMoney(PlayerInfo::getAttribute(Attributes::MONEY));
    const Inventory *const inv = PlayerInfo::getInventory();
    for (int f = 0; f < count; f ++)
    {
        const int price = msg.readInt32("price");
        const int amount = msg.readInt16("amount");
        const ItemTypeT itemType = static_cast<ItemTypeT>(
            msg.readUInt8("item type"));
        const int itemId = msg.readInt16("item id");

        if (!inv)
            continue;
        const Item *const item = inv->findItem(itemId, ItemColor_one);
        if (!item)
            continue;
        // +++ need add colors support
        dialog->addItem(itemId, itemType, ItemColor_one, amount, price);
    }
}
예제 #5
0
MailWindow::MailWindow() :
    // TRANSLATORS: mail window name
    Window(_("Mail"), Modal_false, nullptr, "mail.xml"),
    ActionListener(),
    mMessages(),
    mMessagesMap(),
    mMailModel(new ExtendedNamesModel),
    mListBox(CREATEWIDGETR(ExtendedListBox,
        this, mMailModel, "extendedlistbox.xml")),
    mListScrollArea(new ScrollArea(this, mListBox,
        fromBool(getOptionBool("showlistbackground"), Opaque),
        "mail_listbackground.xml")),
    // TRANSLATORS: mail window button
    mRefreshButton(new Button(this, _("Refresh"), "refresh", this)),
    // TRANSLATORS: mail window button
    mNewButton(new Button(this, _("New"), "new", this)),
    // TRANSLATORS: mail window button
    mDeleteButton(new Button(this, _("Delete"), "delete", this)),
    // TRANSLATORS: mail window button
    mReturnButton(new Button(this, _("Return"), "return", this)),
    // TRANSLATORS: mail window button
    mOpenButton(new Button(this, _("Open"), "open", this))
{
    setWindowName("Mail");
    setCloseButton(true);
    setResizable(true);
    setCloseButton(true);
    setSaveVisible(true);
    setStickyButtonLock(true);

    if (setupWindow)
        setupWindow->registerWindowForReset(this);

    setDefaultSize(310, 180, ImagePosition::CENTER);
    setMinWidth(310);
    setMinHeight(250);
    center();

    mListScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);

    ContainerPlacer placer;
    placer = getPlacer(0, 0);

    placer(0, 0, mListScrollArea, 4, 5).setPadding(3);
    placer(4, 0, mRefreshButton);
    placer(4, 1, mOpenButton);
    placer(4, 2, mNewButton);
    placer(4, 3, mDeleteButton);
    placer(4, 4, mReturnButton);

    Layout &layout = getLayout();
    layout.setRowHeight(0, LayoutType::SET);

    loadWindowState();
    enableVisibleSound(true);
}
예제 #6
0
EmoteWindow::EmoteWindow() :
    // TRANSLATORS: emotes window name
    Window(_("Emotes"), Modal_false, nullptr, "emotes.xml"),
    mTabs(CREATEWIDGETR(TabbedArea, this)),
    mEmotePage(new EmotePage(this)),
    mColorModel(ColorModel::createDefault(this)),
    mColorPage(CREATEWIDGETR(ColorPage, this, mColorModel, "colorpage.xml")),
    mScrollColorPage(new ScrollArea(this, mColorPage, Opaque_false,
        "emotepage.xml")),
    mFontModel(new NamesModel),
    mFontPage(CREATEWIDGETR(ListBox, this, mFontModel, "")),
    mScrollFontPage(new ScrollArea(this, mFontPage, Opaque_false,
        "fontpage.xml")),
    mImageSet(Theme::getImageSetFromThemeXml("emotetabs.xml", "", 17, 16))
{
    setShowTitle(false);
    setResizable(true);

    if (setupWindow)
        setupWindow->registerWindowForReset(this);

    addMouseListener(this);
}
예제 #7
0
PopupList::PopupList(DropDown *const widget,
                     ListModel *const listModel,
                     const bool extended,
                     const Modal modal) :
    Popup("PopupList", "popuplist.xml"),
    FocusListener(),
    mListModel(listModel),
    mListBox(extended ? CREATEWIDGETR(ExtendedListBox,
        widget, listModel, "extendedlistbox.xml", 0) :
        CREATEWIDGETR(ListBox,
        widget, listModel, "popuplistbox.xml")),
    mScrollArea(new ScrollArea(this, mListBox, Opaque_false)),
    mDropDown(widget),
    mPressedIndex(-2),
    mModal(modal)
{
    mListBox->setMouseConsume(false);
    mScrollArea->setMouseConsume(false);
    mAllowLogic = false;
    setFocusable(true);

    mListBox->setDistributeMousePressed(true);
    mScrollArea->setPosition(mPadding, mPadding);
}
예제 #8
0
void SkillRecv::processSkillWarpPoint(Net::MessageIn &msg)
{
    const int skillId = msg.readInt16("skill id");

    TextSelectDialog *const dialog = CREATEWIDGETR(TextSelectDialog,
        // TRANSLATORS: warp select window name
        _("Select warp target"),
        // TRANSLATORS: warp select button
        _("Warp"),
        AllowQuit_false);
    skillWarpListener.setDialog(dialog);
    skillWarpListener.setSkill(skillId);
    dialog->addActionListener(&skillWarpListener);
    for (int f = 0; f < 4; f ++)
        dialog->addText(msg.readString(16, "map name"));
}
예제 #9
0
void LoginDialog::action(const ActionEvent &event)
{
    const std::string &eventId = event.getId();
    if (eventId == "login" && canSubmit())
    {
        prepareUpdate();
        mLoginData->registerLogin = false;
        client->setState(STATE_LOGIN_ATTEMPT);
    }
    else if (eventId == "server")
    {
        close();
    }
    else if (eventId == "register")
    {
        if (loginHandler->isRegistrationEnabled())
        {
            prepareUpdate();
            client->setState(STATE_REGISTER_PREP);
        }
        else if (!mLoginData->registerUrl.empty())
        {
            const std::string &url = mLoginData->registerUrl;
            urlListener.url = url;
            ConfirmDialog *const confirmDlg = CREATEWIDGETR(ConfirmDialog,
                // TRANSLATORS: question dialog
                _("Open register url"),
                url,
                SOUND_REQUEST,
                false,
                Modal_true);
            confirmDlg->addActionListener(&urlListener);
        }
    }
    else if (eventId == "customhost")
    {
        mUpdateHostText->setVisible(fromBool(
            mCustomUpdateHost->isSelected(), Visible));
    }
    else if (eventId == "updateselect")
    {
        mCustomUpdateHost->setSelected(false);
        mUpdateHostText->setVisible(Visible_false);
    }
}
예제 #10
0
SetupWindow::SetupWindow() :
    // TRANSLATORS: setup window name
    Window(_("Setup"), Modal_false, nullptr, "setup.xml"),
    ActionListener(),
    mTabs(),
    mWindowsToReset(),
    mButtons(),
    mModsTab(nullptr),
    mQuickTab(nullptr),
    mResetWindows(nullptr),
    mPanel(CREATEWIDGETR(TabbedArea, this)),
    mVersion(new Label(this, FULL_VERSION)),
    mButtonPadding(5)
{
    setCloseButton(true);
    setResizable(true);
    setStickyButtonLock(true);
}
예제 #11
0
WorldSelectDialog::WorldSelectDialog(Worlds worlds) :
    // TRANSLATORS: world select dialog name
    Window(_("Select World"), Modal_false, nullptr, "world.xml"),
    ActionListener(),
    KeyListener(),
    mWorldListModel(new WorldListModel(worlds)),
    mWorldList(CREATEWIDGETR(ListBox, this, mWorldListModel, "")),
    // TRANSLATORS: world dialog button
    mChangeLoginButton(new Button(this, _("Change Login"), "login", this)),
    // TRANSLATORS: world dialog button
    mChooseWorld(new Button(this, _("Choose World"), "world", this))
{
    ScrollArea *const worldsScroll = new ScrollArea(this, mWorldList,
        getOptionBool("showbackground"), "world_background.xml");

    worldsScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);

    place(0, 0, worldsScroll, 3, 5).setPadding(2);
    place(1, 5, mChangeLoginButton);
    place(2, 5, mChooseWorld);

    // Make sure the list has enough height
    getLayout().setRowHeight(0, 60);

    reflowLayout(0, 0);

    if (worlds.empty())
    {
        // Disable Ok button
        mChooseWorld->setEnabled(false);
    }
    else
    {
        // Select first server
        mWorldList->setSelected(0);
    }

    addKeyListener(this);

    center();
}
예제 #12
0
DebugWindow::DebugWindow() :
    // TRANSLATORS: debug window name
    Window(_("Debug"), Modal_false, nullptr, "debug.xml"),
    mTabs(CREATEWIDGETR(TabbedArea, this)),
    mMapWidget(new MapDebugTab(this)),
    mTargetWidget(new TargetDebugTab(this)),
    mNetWidget(new NetDebugTab(this))
{
    setWindowName("Debug");
    if (setupWindow)
        setupWindow->registerWindowForReset(this);

    setResizable(true);
    setCloseButton(true);
    setSaveVisible(true);
    setStickyButtonLock(true);

    setDefaultSize(400, 300, ImagePosition::CENTER);

    mTabs->setSelectable(false);
    mTabs->getWidgetContainer()->setSelectable(false);
    mTabs->getTabContainer()->setSelectable(false);
    // TRANSLATORS: debug window tab
    mTabs->addTab(std::string(_("Map")), mMapWidget);
    // TRANSLATORS: debug window tab
    mTabs->addTab(std::string(_("Target")), mTargetWidget);
    // TRANSLATORS: debug window tab
    mTabs->addTab(std::string(_("Net")), mNetWidget);

    mTabs->setDimension(Rect(0, 0, 600, 300));

    const int w = mDimension.width;
    const int h = mDimension.height;
    mMapWidget->resize(w, h);
    mTargetWidget->resize(w, h);
    mNetWidget->resize(w, h);
    loadWindowState();
    enableVisibleSound(true);
}
예제 #13
0
void SellDialog::postInit()
{
    setWindowName("Sell");
    setResizable(true);
    setCloseButton(true);
    setStickyButtonLock(true);
    setMinWidth(260);
    setMinHeight(220);
    setDefaultSize(260, 230, ImagePosition::CENTER);

    if (setupWindow)
        setupWindow->registerWindowForReset(this);

    // Create a ShopItems instance, that is aware of duplicate entries.
    mShopItems = new ShopItems(true);

    if (mAdvanced == Advanced_true)
        mShopItems->setMergeDuplicates(false);

    mShopItemList = CREATEWIDGETR(ShopListBox,
        this,
        mShopItems,
        mShopItems,
        ShopListBoxType::Unknown);
    mShopItemList->setProtectItems(true);
    mScrollArea = new ScrollArea(this, mShopItemList,
        fromBool(getOptionBool("showbackground"), Opaque),
        "sell_background.xml");
    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);

    mSellButton = new Button(this,
        // TRANSLATORS: sell dialog button
        mAdvanced == Advanced_true ? _("Add") : _("Sell"),
        "presell",
        this);
    // TRANSLATORS: sell dialog button
    mQuitButton = new Button(this, _("Quit"), "quit", this);

    initButtons();

    mSellButton->setEnabled(false);

    mShopItemList->setDistributeMousePressed(false);
    mShopItemList->setPriceCheck(false);
    mShopItemList->addSelectionListener(this);
    mShopItemList->setActionEventId("sell");
    mShopItemList->addActionListener(this);

    ContainerPlacer placer;
    placer = getPlacer(0, 0);

    if (mIsSell == IsSell_true)
    {
        // TRANSLATORS: sell dialog button
        mIncreaseButton = new Button(this, _("+"), "inc", this);
        // TRANSLATORS: sell dialog button
        mDecreaseButton = new Button(this, _("-"), "dec", this);
        // TRANSLATORS: sell dialog button
        mAddMaxButton = new Button(this, _("Max"), "max", this);
        mSlider = new Slider(this, 1.0, 1.0);

        mQuantityLabel = new Label(this, strprintf(
            "%d / %d", mAmountItems, mMaxItems));
        mQuantityLabel->setAlignment(Graphics::CENTER);
        // TRANSLATORS: sell dialog label
        mMoneyLabel = new Label(this, strprintf(_("Price: %s / Total: %s"),
            "", ""));
        if (mAdvanced == Advanced_true)
        {
            // TRANSLATORS: sell dialog button
            mConfirmButton = new Button(this, _("Sell"), "confirm", this);
            mConfirmButton->setEnabled(false);
        }

        mDecreaseButton->adjustSize();
        mDecreaseButton->setWidth(mIncreaseButton->getWidth());
        mIncreaseButton->setEnabled(false);
        mDecreaseButton->setEnabled(false);
        mSlider->setEnabled(false);
        mSlider->setActionEventId("slider");
        mSlider->addActionListener(this);

        placer(0, 0, mScrollArea, 8, 5).setPadding(3);
        placer(0, 5, mDecreaseButton);
        placer(1, 5, mSlider, 3);
        placer(4, 5, mIncreaseButton);
        placer(5, 5, mQuantityLabel, 2);
        placer(7, 5, mAddMaxButton);
        placer(0, 6, mMoneyLabel, 8);
        if (mAdvanced == Advanced_true)
        {
            placer(5, 7, mSellButton);
            placer(6, 7, mConfirmButton);
        }
        else
        {
            placer(6, 7, mSellButton);
        }
        placer(7, 7, mQuitButton);
    }
    else
    {
        placer(0, 0, mScrollArea, 8, 5).setPadding(3);
        placer(6, 5, mSellButton);
        placer(7, 5, mQuitButton);
    }

    Layout &layout = getLayout();
    layout.setRowHeight(0, LayoutType::SET);

    center();
    loadWindowState();

    instances.push_back(this);
    setVisible(Visible_true);
    enableVisibleSound(true);
}
예제 #14
0
Setup_Video::Setup_Video(const Widget2 *const widget) :
    SetupTab(widget),
    KeyListener(),
    mFullScreenEnabled(config.getBoolValue("screen")),
    mOpenGLEnabled(intToRenderType(config.getIntValue("opengl"))),
    mFps(config.getIntValue("fpslimit")),
    mAltFps(config.getIntValue("altfpslimit")),
    mModeListModel(new ModeListModel),
    mOpenGLListModel(new OpenGLListModel),
    mModeList(CREATEWIDGETR(ListBox, widget, mModeListModel, "")),
    // TRANSLATORS: video settings checkbox
    mFsCheckBox(new CheckBox(this, _("Full screen"), mFullScreenEnabled)),
    mOpenGLDropDown(new DropDown(widget, mOpenGLListModel)),
    // TRANSLATORS: video settings checkbox
    mFpsCheckBox(new CheckBox(this, _("FPS limit:"))),
    mFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
    mFpsLabel(new Label(this)),
    mAltFpsSlider(new Slider(this, 2.0, 160.0, 1.0)),
    // TRANSLATORS: video settings label
    mAltFpsLabel(new Label(this, _("Alt FPS limit: "))),
#if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
    // TRANSLATORS: video settings button
    mDetectButton(new Button(this, _("Detect best mode"), "detect", this)),
#endif  // !defined(ANDROID) && !defined(__APPLE__) &&
        // !defined(__native_client__)
    mDialog(nullptr),
    mCustomCursorEnabled(config.getBoolValue("customcursor")),
    mEnableResize(config.getBoolValue("enableresize")),
    mNoFrame(config.getBoolValue("noframe")),
    mCustomCursorCheckBox(new CheckBox(this,
#ifdef ANDROID
        // TRANSLATORS: video settings checkbox
        _("Show cursor"),
#else  // ANDROID
        // TRANSLATORS: video settings checkbox
        _("Custom cursor"),
#endif  // ANDROID
        mCustomCursorEnabled)),
    // TRANSLATORS: video settings checkbox
    mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"),
                          mEnableResize)),
    // TRANSLATORS: video settings checkbox
    mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame))
{
    // TRANSLATORS: video settings tab name
    setName(_("Video"));

    ScrollArea *const scrollArea = new ScrollArea(this, mModeList,
        Opaque_true, "setup_video_background.xml");
    scrollArea->setWidth(150);
    scrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);

    mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]);

    mModeList->setEnabled(true);

    // TRANSLATORS: video settings label
    mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
    mFpsLabel->setWidth(60);
    // TRANSLATORS: video settings label
    mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0 ?
        // TRANSLATORS: video settings label value
        toString(mAltFps) : _("None")));
    mAltFpsLabel->setWidth(150);
    mFpsSlider->setEnabled(mFps > 0);
    mFpsSlider->setValue(mFps);
    mAltFpsSlider->setEnabled(mAltFps > 0);
    mAltFpsSlider->setValue(mAltFps);
    mFpsCheckBox->setSelected(mFps > 0);

    // Pre-select the current video mode.
    const std::string videoMode = toString(
        mainGraphics->mActualWidth).append("x").append(
        toString(mainGraphics->mActualHeight));
    mModeList->setSelected(mModeListModel->getIndexOf(videoMode));

    mModeList->setActionEventId("videomode");
    mCustomCursorCheckBox->setActionEventId("customcursor");
    mFpsCheckBox->setActionEventId("fpslimitcheckbox");
    mFpsSlider->setActionEventId("fpslimitslider");
    mAltFpsSlider->setActionEventId("altfpslimitslider");
    mOpenGLDropDown->setActionEventId("opengl");
    mEnableResizeCheckBox->setActionEventId("enableresize");
    mNoFrameCheckBox->setActionEventId("noframe");

    mModeList->addActionListener(this);
    mCustomCursorCheckBox->addActionListener(this);
    mFpsCheckBox->addActionListener(this);
    mFpsSlider->addActionListener(this);
    mAltFpsSlider->addActionListener(this);
    mOpenGLDropDown->addActionListener(this);
    mEnableResizeCheckBox->addActionListener(this);
    mNoFrameCheckBox->addActionListener(this);

    // Do the layout
    LayoutHelper h(this);
    ContainerPlacer place = h.getPlacer(0, 0);

    place(0, 0, scrollArea, 1, 5).setPadding(2);
    place(0, 5, mOpenGLDropDown, 1);

    place(1, 0, mFsCheckBox, 2);

    place(1, 1, mCustomCursorCheckBox, 3);

    place(1, 2, mEnableResizeCheckBox, 2);
    place(1, 3, mNoFrameCheckBox, 2);

    place(0, 6, mFpsSlider);
    place(1, 6, mFpsCheckBox).setPadding(3);
    place(2, 6, mFpsLabel).setPadding(1);

    place(0, 7, mAltFpsSlider);
    place(1, 7, mAltFpsLabel).setPadding(3);

#if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
    place(0, 8, mDetectButton);
#else  // !defined(ANDROID) && !defined(__APPLE__) &&
       // !defined(__native_client__)
    mNoFrameCheckBox->setEnabled(false);
    mEnableResizeCheckBox->setEnabled(false);
#ifndef __native_client__
    mFsCheckBox->setEnabled(false);
#endif  // __native_client__
#endif  // !defined(ANDROID) && !defined(__APPLE__) &&
        // !defined(__native_client__)

    int width = 600;

    if (config.getIntValue("screenwidth") >= 730)
        width += 100;

    setDimension(Rect(0, 0, width, 300));
}
예제 #15
0
void RegisterDialog::action(const ActionEvent &event)
{
    const std::string &eventId = event.getId();
    if (eventId == "cancel")
    {
        close();
    }
    else if (eventId == "register" && canSubmit())
    {
        const std::string &user = mUserField->getText();
        logger->log("RegisterDialog::register Username is %s", user.c_str());

        std::string errorMsg;
        int error = 0;

        const unsigned int minUser = loginHandler->getMinUserNameLength();
        const unsigned int maxUser = loginHandler->getMaxUserNameLength();
        const unsigned int minPass = loginHandler->getMinPasswordLength();
        const unsigned int maxPass = loginHandler->getMaxPasswordLength();

        if (user.length() < minUser)
        {
            // Name too short
            errorMsg = strprintf
                // TRANSLATORS: error message
                (_("The username needs to be at least %u characters long."),
                 minUser);
            error = 1;
        }
        else if (user.length() > maxUser - 1)
        {
            // Name too long
            errorMsg = strprintf
                // TRANSLATORS: error message
                (_("The username needs to be less than %u characters long."),
                 maxUser);
            error = 1;
        }
        else if (mPasswordField->getText().length() < minPass)
        {
            // Pass too short
            errorMsg = strprintf
                // TRANSLATORS: error message
                (_("The password needs to be at least %u characters long."),
                 minPass);
            error = 2;
        }
        else if (mPasswordField->getText().length() > maxPass)
        {
            // Pass too long
            errorMsg = strprintf
                // TRANSLATORS: error message
                (_("The password needs to be less than %u characters long."),
                 maxPass);
            error = 2;
        }
        else if (mPasswordField->getText() != mConfirmField->getText())
        {
            // Password does not match with the confirmation one
            // TRANSLATORS: error message
            errorMsg = _("Passwords do not match.");
            error = 2;
        }
        else if (mEmailField &&
                 mEmailField->getText().find('@') == std::string::npos)
        {
            // TRANSLATORS: error message
            errorMsg = _("Incorrect email.");
            error = 1;
        }
        else if (mEmailField && mEmailField->getText().size() > 40)
        {
            // TRANSLATORS: error message
            errorMsg = _("Email too long.");
            error = 1;
        }

        if (error > 0)
        {
            if (error == 1)
            {
                mWrongDataNoticeListener->setTarget(this->mUserField);
            }
            else if (error == 2)
            {
                // Reset password confirmation
                mPasswordField->setText("");
                mConfirmField->setText("");
                mWrongDataNoticeListener->setTarget(this->mPasswordField);
            }

            OkDialog *const dlg = CREATEWIDGETR(OkDialog,
                // TRANSLATORS: error message
                _("Error"), errorMsg, _("OK"),
                DialogType::ERROR,
                Modal_true,
                ShowCenter_true,
                nullptr,
                260);
            dlg->addActionListener(mWrongDataNoticeListener);
        }
        else
        {
            // No errors detected, register the new user.
            mRegisterButton->setEnabled(false);
            mLoginData->username = mUserField->getText();
            mLoginData->password = mPasswordField->getText();
            if (features.getIntValue("forceAccountGender") == -1)
            {
                if (mFemaleButton && mFemaleButton->isSelected())
                    mLoginData->gender = Gender::FEMALE;
                else if (mOtherButton && mOtherButton->isSelected())
                    mLoginData->gender = Gender::OTHER;
                else
                    mLoginData->gender = Gender::MALE;
            }
            else
            {
                mLoginData->gender = Being::intToGender(
                    CAST_U8(features.getIntValue("forceAccountGender")));
            }

            if (mEmailField)
                mLoginData->email = mEmailField->getText();
            mLoginData->registerLogin = true;

            client->setState(State::REGISTER_ATTEMPT);
        }
    }
}
예제 #16
0
void EditServerDialog::action(const ActionEvent &event)
{
    const std::string &eventId = event.getId();

    if (eventId == "ok")
    {
        // Give focus back to the server dialog.
        mServerAddressField->requestFocus();
    }
    if (eventId == "addServer" || eventId == "connect")
    {
        // Check the given information
        if (mServerAddressField->getText().empty()
            || mPortField->getText().empty())
        {
            OkDialog *const dlg = CREATEWIDGETR(OkDialog,
                // TRANSLATORS: edit server dialog error header
                _("Error"),
                // TRANSLATORS: edit server dialog error message
                _("Please at least type both the address and the port "
                  "of the server."),
                // TRANSLATORS: ok dialog button
                _("OK"),
                DialogType::ERROR,
                Modal_true,
                ShowCenter_true,
                nullptr,
                260);
            dlg->addActionListener(this);
        }
        else
        {
            mCancelButton->setEnabled(false);
            mOkButton->setEnabled(false);

            mServer.name = mNameField->getText();
            mServer.description = mDescriptionField->getText();
            mServer.onlineListUrl = mOnlineListUrlField->getText();
            mServer.hostname = mServerAddressField->getText();
            mServer.packetVersion = mPacketVersionField->getValue();
            mServer.port = CAST_S16(atoi(
                mPortField->getText().c_str()));
            mServer.persistentIp = mPersistentIp->isSelected();

            if (mTypeField)
            {
                switch (mTypeField->getSelected())
                {
#ifdef TMWA_SUPPORT
                    case 0:
                        mServer.type = ServerType::TMWATHENA;
                        break;
                    case 1:
                        mServer.type = ServerType::EATHENA;
                        break;
                    case 2:
                        mServer.type = ServerType::EVOL2;
                        break;
#else  // TMWA_SUPPORT

                    case 0:
                        mServer.type = ServerType::EATHENA;
                        break;
                    case 1:
                        mServer.type = ServerType::EVOL2;
                        break;
#endif  // TMWA_SUPPORT

                    default:
                        mServer.type = ServerType::UNKNOWN;
                        break;
                }
            }
            else
            {
                mServer.type = ServerType::TMWATHENA;
            }

            // Tell the server has to be saved
            mServer.save = true;

            // Add server
            mServerDialog->updateServer(mServer, mIndex);
            if (eventId == "connect")
                mServerDialog->connectToSelectedServer();
            scheduleDelete();
        }
    }
    else if (eventId == "cancel")
    {
        scheduleDelete();
    }
}
예제 #17
0
NpcDialog::NpcDialog(const BeingId npcId) :
    // TRANSLATORS: npc dialog name
    Window(_("NPC"), Modal_false, nullptr, "npc.xml"),
    ActionListener(),
    mNpcId(npcId),
    mDefaultInt(0),
    mDefaultString(),
    mTextBox(new BrowserBox(this, BrowserBox::AUTO_WRAP, true,
        "browserbox.xml")),
    mScrollArea(new ScrollArea(this, mTextBox,
        getOptionBool("showtextbackground"), "npc_textbackground.xml")),
    mText(),
    mNewText(),
    mItemList(CREATEWIDGETR(ExtendedListBox,
        this, this, "extendedlistbox.xml")),
    mListScrollArea(new ScrollArea(this, mItemList,
        getOptionBool("showlistbackground"), "npc_listbackground.xml")),
    mItems(),
    mImages(),
    mItemLinkHandler(new ItemLinkHandler),
    mTextField(new TextField(this, "")),
    mIntField(new IntTextField(this)),
    // TRANSLATORS: npc dialog button
    mPlusButton(new Button(this, _("+"), "inc", this)),
    // TRANSLATORS: npc dialog button
    mMinusButton(new Button(this, _("-"), "dec", this)),
    // TRANSLATORS: npc dialog button
    mClearButton(new Button(this, _("Clear"), "clear", this)),
    mButton(new Button(this, "", "ok", this)),
    // TRANSLATORS: npc dialog button
    mButton2(new Button(this, _("Close"), "close", this)),
    // TRANSLATORS: npc dialog button
    mButton3(new Button(this, _("Add"), "add", this)),
    // TRANSLATORS: npc dialog button
    mResetButton(new Button(this, _("Reset"), "reset", this)),
    mInventory(new Inventory(InventoryType::NPC, 1)),
    mItemContainer(new ItemContainer(this, mInventory)),
    mItemScrollArea(new ScrollArea(this, mItemContainer,
        getOptionBool("showitemsbackground"), "npc_listbackground.xml")),
    mInputState(NPC_INPUT_NONE),
    mActionState(NPC_ACTION_WAIT),
    mPlayerBox(new PlayerBox(nullptr)),
    mAvatarBeing(nullptr),
    mLastNextTime(0),
    mCameraMode(-1),
    mCameraX(0),
    mCameraY(0),
    mShowAvatar(false),
    mLogInteraction(config.getBoolValue("logNpcInGui"))
{
    // Basic Window Setup
    setWindowName("NpcText");
    setResizable(true);
    setFocusable(true);
    setStickyButtonLock(true);

    setMinWidth(200);
    setMinHeight(150);

    setDefaultSize(300, 578, ImageRect::LOWER_LEFT);

    mPlayerBox->setWidth(70);
    mPlayerBox->setHeight(100);

    // Setup output text box
    mTextBox->setOpaque(false);
    mTextBox->setMaxRow(config.getIntValue("ChatLogLength"));
    mTextBox->setLinkHandler(mItemLinkHandler);
    mTextBox->setProcessVars(true);
    mTextBox->setFont(gui->getNpcFont());
    mTextBox->setEnableKeys(true);
    mTextBox->setEnableTabs(true);

    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
    mScrollArea->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS);

    // Setup listbox
    mItemList->setWrappingEnabled(true);
    mItemList->setActionEventId("ok");
    mItemList->addActionListener(this);
    mItemList->setDistributeMousePressed(false);
    mItemList->setFont(gui->getNpcFont());
    if (gui->getNpcFont()->getHeight() < 20)
        mItemList->setRowHeight(20);
    else
        mItemList->setRowHeight(gui->getNpcFont()->getHeight());

    setContentSize(260, 175);
    mListScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
    mItemScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
    mItemList->setVisible(Visible_true);
    mTextField->setVisible(Visible_true);
    mIntField->setVisible(Visible_true);

    const Font *const fnt = mButton->getFont();
    int width = std::max(fnt->getWidth(CAPTION_WAITING),
        fnt->getWidth(CAPTION_NEXT));
    width = std::max(width, fnt->getWidth(CAPTION_CLOSE));
    width = std::max(width, fnt->getWidth(CAPTION_SUBMIT));
    mButton->setWidth(8 + width);

    // Place widgets
    buildLayout();

    center();
    loadWindowState();

    instances.push_back(this);
}
예제 #18
0
ShopWindow::ShopWindow() :
    // TRANSLATORS: shop window name
    Window(_("Personal Shop"), Modal_false, nullptr, "shop.xml"),
#ifdef EATHENA_SUPPORT
    VendingModeListener(),
    VendingSlotsListener(),
    BuyingStoreModeListener(),
    BuyingStoreSlotsListener(),
#endif
    ActionListener(),
    SelectionListener(),
    // TRANSLATORS: shop window button
    mCloseButton(new Button(this, _("Close"), "close", this)),
    mBuyShopItems(new ShopItems),
    mSellShopItems(new ShopItems),
    mTradeItem(nullptr),
    mBuyShopItemList(CREATEWIDGETR(ShopListBox,
        this, mBuyShopItems, mBuyShopItems)),
    mSellShopItemList(CREATEWIDGETR(ShopListBox,
        this, mSellShopItems, mSellShopItems)),
    mCurrentShopItemList(nullptr),
    mScrollArea(new ScrollArea(this, mBuyShopItemList,
        getOptionBool("showbuybackground"), "shop_buy_background.xml")),
    // TRANSLATORS: shop window label
    mAddButton(new Button(this, _("Add"), "add", this)),
    // TRANSLATORS: shop window label
    mDeleteButton(new Button(this, _("Delete"), "delete", this)),
    mAnnounceButton(nullptr),
    mPublishButton(nullptr),
    mRenameButton(nullptr),
    mAnnounceLinks(nullptr),
    mTabs(nullptr),
    mAcceptPlayer(),
    mTradeNick(),
    mSellShopName(serverConfig.getStringValue("sellShopName")),
    mSelectedItem(-1),
    mAnnonceTime(0),
    mLastRequestTimeList(0),
    mLastRequestTimeItem(0),
    mRandCounter(0),
    mTradeMoney(0),
    mSellShopSize(0),
    mBuyShopSize(0),
    isBuySelected(true),
    mHaveVending(serverFeatures->haveVending()),
    mEnableBuyingStore(false),
    mEnableVending(false)
{
    setWindowName("Personal Shop");
    setResizable(true);
    setCloseButton(true);
    setStickyButtonLock(true);
    setMinWidth(300);
    setMinHeight(220);
    if (mainGraphics->mWidth > 600)
        setDefaultSize(500, 300, ImagePosition::CENTER);
    else
        setDefaultSize(380, 300, ImagePosition::CENTER);

    if (setupWindow)
        setupWindow->registerWindowForReset(this);

    const int size = config.getIntValue("fontSize")
        + getOption("tabHeightAdjust", 16);
    mTabs = new TabStrip(this, "shop", size);
    mTabs->addActionListener(this);
    mTabs->setActionEventId("tab_");
    // TRANSLATORS: shop window tab name
    mTabs->addButton(_("Buy"), "buy", true);
    // TRANSLATORS: shop window tab name
    mTabs->addButton(_("Sell"), "sell", false);

    loadList();

    mBuyShopItemList->setPriceCheck(false);
    mSellShopItemList->setPriceCheck(false);

    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);

    mBuyShopItemList->addSelectionListener(this);
    mSellShopItemList->addSelectionListener(this);

    ContainerPlacer placer;
    placer = getPlacer(0, 0);

    placer(0, 0, mTabs, 8).setPadding(3);

    if (mHaveVending)
    {
        // TRANSLATORS: shop window button
        mPublishButton = new Button(this, _("Publish"), "publish", this);
        // TRANSLATORS: shop window button
        mRenameButton = new Button(this, _("Rename"), "rename", this);
        placer(2, 6, mPublishButton);
        placer(3, 6, mRenameButton);
    }
    else
    {
        // TRANSLATORS: shop window button
        mAnnounceButton = new Button(this, _("Announce"), "announce", this);
        // TRANSLATORS: shop window checkbox
        mAnnounceLinks = new CheckBox(this, _("Show links in announce"), false,
            this, "link announce");

        placer(2, 6, mAnnounceButton);
        placer(0, 7, mAnnounceLinks, 7);
    }

    placer(0, 1, mScrollArea, 8, 5).setPadding(3);
    placer(0, 6, mAddButton);
    placer(1, 6, mDeleteButton);
    placer(7, 6, mCloseButton);

    Layout &layout = getLayout();
    layout.setRowHeight(0, LayoutType::SET);

    center();
    loadWindowState();
#ifdef EATHENA_SUPPORT
    updateShopName();
#endif
    instances.push_back(this);
}
예제 #19
0
void TextSelectDialog::postInit()
{
    Window::postInit();
    setWindowName("TextSelectDialog");
    setResizable(true);
    setCloseButton(mAllowQuit == AllowQuit_true);
    setStickyButtonLock(true);
    setMinWidth(260);
    setMinHeight(220);
    setDefaultSize(260, 230, ImagePosition::CENTER, 0, 0);

    if (setupWindow != nullptr)
        setupWindow->registerWindowForReset(this);

    setActionEventId("OK");
    mModel = new NamesModel;
    mItemList = CREATEWIDGETR(ListBox,
        this,
        mModel,
        "listbox.xml");
    mScrollArea = new ScrollArea(this, mItemList,
        fromBool(getOptionBool("showbackground", false), Opaque),
        "sell_background.xml");
    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);

    mSelectButton = new Button(this,
        mSelectButtonName,
        "select",
        BUTTON_SKIN,
        this);
    if (mAllowQuit == AllowQuit_true)
    {
        mQuitButton = new Button(this,
            // TRANSLATORS: sell dialog button
            _("Quit"),
            "quit",
            BUTTON_SKIN,
            this);
    }

    mSelectButton->setEnabled(false);

    mItemList->setDistributeMousePressed(false);
    mItemList->addSelectionListener(this);
    mItemList->setActionEventId("item");
    mItemList->addActionListener(this);

    ContainerPlacer placer(nullptr, nullptr);
    placer = getPlacer(0, 0);

    placer(0, 0, mScrollArea, 8, 5).setPadding(3);
    if (mQuitButton != nullptr)
    {
        placer(6, 5, mSelectButton, 1, 1);
        placer(7, 5, mQuitButton, 1, 1);
    }
    else
    {
        placer(7, 5, mSelectButton, 1, 1);
    }

    Layout &layout = getLayout();
    layout.setRowHeight(0, LayoutType::SET);

    center();
    loadWindowState();

    setVisible(Visible_true);
    enableVisibleSound(true);
}
예제 #20
0
DropDown::DropDown(const Widget2 *const widget,
                   ListModel *const listModel,
                   const bool extended,
                   const Modal modal,
                   ActionListener *const listener,
                   const std::string &eventId) :
    ActionListener(),
    BasicContainer(widget),
    KeyListener(),
    MouseListener(),
    FocusListener(),
    SelectionListener(),
    mPopup(CREATEWIDGETR(PopupList, this, listModel, extended, modal)),
    mShadowColor(getThemeColor(ThemeColorId::DROPDOWN_SHADOW)),
    mHighlightColor(getThemeColor(ThemeColorId::HIGHLIGHT)),
    mPadding(1),
    mImagePadding(2),
    mSpacing(0),
    mFoldedUpHeight(0),
    mSelectionListeners(),
    mExtended(extended),
    mDroppedDown(false),
    mPushed(false),
    mIsDragged(false)
{
    mAllowLogic = false;
    mFrameSize = 2;
    mForegroundColor2 = getThemeColor(ThemeColorId::DROPDOWN_OUTLINE);

    mPopup->setHeight(100);

    // Initialize graphics
    if (instances == 0 && theme)
    {
        // Load the background skin
        for (int i = 0; i < 2; i ++)
        {
            Skin *const skin = theme->load(dropdownFiles[i], "dropdown.xml");
            if (skin)
            {
                if (!i)
                    mSkin = skin;
                const ImageRect &rect = skin->getBorder();
                for (int f = 0; f < 2; f ++)
                {
                    if (rect.grid[f])
                    {
                        rect.grid[f]->incRef();
                        buttons[f][i] = rect.grid[f];
                        buttons[f][i]->setAlpha(mAlpha);
                    }
                    else
                    {
                        buttons[f][i] = nullptr;
                    }
                }
                if (i)
                    theme->unload(skin);
            }
            else
            {
                for (int f = 0; f < 2; f ++)
                    buttons[f][i] = nullptr;
            }
        }

        // get the border skin
        theme->loadRect(skinRect, "dropdown_background.xml", "");
    }

    instances++;

    setWidth(100);
    setFocusable(true);
    setListModel(listModel);

    if (mPopup->getSelected() < 0)
        mPopup->setSelected(0);

    addMouseListener(this);
    addKeyListener(this);
    addFocusListener(this);

    adjustHeight();
//    mPopup->setForegroundColorAll(getThemeColor(ThemeColorId::DROPDOWN),
//        getThemeColor(ThemeColorId::DROPDOWN_OUTLINE));
    mForegroundColor = getThemeColor(ThemeColorId::DROPDOWN);
    mForegroundColor2 = getThemeColor(ThemeColorId::DROPDOWN_OUTLINE);

    if (!eventId.empty())
        setActionEventId(eventId);

    if (listener)
        addActionListener(listener);

    mPopup->adjustSize();

    if (mSkin)
    {
        mSpacing = mSkin->getOption("spacing");
        mFrameSize = CAST_U32(mSkin->getOption("frameSize"));
        mPadding = mSkin->getPadding();
        mImagePadding = mSkin->getOption("imagePadding");
    }
    adjustHeight();
}
예제 #21
0
ServerDialog::ServerDialog(ServerInfo *const serverInfo,
                           const std::string &dir) :
    // TRANSLATORS: servers dialog name
    Window(_("Choose Your Server"), Modal_false, nullptr, "server.xml"),
    ActionListener(),
    KeyListener(),
    SelectionListener(),
    mMutex(),
    mServers(ServerInfos()),
    mDir(dir),
    mDescription(new Label(this, std::string())),
    // TRANSLATORS: servers dialog button
    mQuitButton(new Button(this, _("Quit"), "quit", this)),
    // TRANSLATORS: servers dialog button
    mConnectButton(new Button(this, _("Connect"), "connect", this)),
    // TRANSLATORS: servers dialog button
    mAddEntryButton(new Button(this, _("Add"), "addEntry", this)),
    // TRANSLATORS: servers dialog button
    mEditEntryButton(new Button(this, _("Edit"), "editEntry", this)),
    // TRANSLATORS: servers dialog button
    mDeleteButton(new Button(this, _("Delete"), "remove", this)),
    // TRANSLATORS: servers dialog button
    mLoadButton(new Button(this, _("Load"), "load", this)),
    mServersListModel(new ServersListModel(&mServers, this)),
    mServersList(CREATEWIDGETR(ServersListBox, this, mServersListModel)),
    mDownload(nullptr),
    mServerInfo(serverInfo),
    mPersistentIPCheckBox(nullptr),
    mDownloadProgress(-1.0F),
    mDownloadStatus(DOWNLOADING_UNKNOWN)
{
    if (isSafeMode)
    {
        // TRANSLATORS: servers dialog name
        setCaption(_("Choose Your Server  *** SAFE MODE ***"));
    }

    setWindowName("ServerDialog");

    setCloseButton(true);

    mPersistentIPCheckBox = new CheckBox(this,
        // TRANSLATORS: servers dialog checkbox
        _("Use same ip for game sub servers"),
        config.getBoolValue("usePersistentIP"),
        this, "persitent ip");

    loadCustomServers();

    mServersList->addMouseListener(this);

    ScrollArea *const usedScroll = new ScrollArea(this, mServersList,
        getOptionBool("showbackground"), "server_background.xml");
    usedScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);

    mServersList->addSelectionListener(this);
    usedScroll->setVerticalScrollAmount(0);

    place(0, 0, usedScroll, 7, 5).setPadding(3);
    place(0, 5, mDescription, 7);
    place(0, 6, mPersistentIPCheckBox, 7);
    place(0, 7, mAddEntryButton);
    place(1, 7, mEditEntryButton);
    place(2, 7, mLoadButton);
    place(3, 7, mDeleteButton);
    place(5, 7, mQuitButton);
    place(6, 7, mConnectButton);

    // Make sure the list has enough height
    getLayout().setRowHeight(0, 80);

    // Do this manually instead of calling reflowLayout so we can enforce a
    // minimum width.
    int width = 500;
    int height = 350;

    getLayout().reflow(width, height);
    setContentSize(width, height);

    setMinWidth(310);
    setMinHeight(220);
    setDefaultSize(getWidth(), getHeight(), ImagePosition::CENTER);

    setResizable(true);
    addKeyListener(this);

    loadWindowState();
}
예제 #22
0
Setup_Input::Setup_Input(const Widget2 *const widget) :
    SetupTab(widget),
    mKeyListModel(new KeyListModel),
    mKeyList(CREATEWIDGETR(ListBox, this, mKeyListModel, "")),
    // TRANSLATORS: button in input settings tab
    mAssignKeyButton(new Button(this, _("Assign"), "assign",
        BUTTON_SKIN, this)),
    // TRANSLATORS: button in input settings tab
    mUnassignKeyButton(new Button(this, _("Unassign"), "unassign",
        BUTTON_SKIN, this)),
    // TRANSLATORS: button in input settings tab
    mDefaultButton(new Button(this, _("Default"), "default",
        BUTTON_SKIN, this)),
    // TRANSLATORS: button in input settings tab
    mResetKeysButton(new Button(this, _("Reset all keys"), "resetkeys",
        BUTTON_SKIN, this)),
    mTabs(new TabStrip(this, config.getIntValue("fontSize") + 10, 0)),
    mScrollArea(new ScrollArea(this, mKeyList,
        Opaque_true, "setup_input_background.xml")),
    mKeySetting(false),
    mActionDataSize(new int [SETUP_PAGES])
{
    inputManager.setSetupInput(this);
    // TRANSLATORS: setting tab name
    setName(_("Input"));

    mKeyListModel->setSelectedData(0);

    for (int f = 0; f < SETUP_PAGES; f ++)
    {
        int cnt = 0;
        while (!setupActionData[f][cnt].name.empty())
            cnt ++;
        mActionDataSize[f] = cnt;
    }

    mKeyListModel->setSize(mActionDataSize[0]);
    refreshKeys();
    if (gui != nullptr)
        mKeyList->setFont(gui->getHelpFont());
    mKeyList->addActionListener(this);

    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
    mAssignKeyButton->addActionListener(this);
    mAssignKeyButton->setEnabled(false);
    mUnassignKeyButton->addActionListener(this);
    mUnassignKeyButton->setEnabled(false);
    mResetKeysButton->addActionListener(this);
    mDefaultButton->addActionListener(this);

    mTabs->addActionListener(this);
    mTabs->setActionEventId("tabs_");
    int k = 0;
    while (pages[k] != nullptr)
    {
        mTabs->addButton(gettext(pages[k]), pages[k], false);
        k ++;
    }

    fixTranslations();

    // Do the layout
    LayoutHelper h(this);
    ContainerPlacer place = h.getPlacer(0, 0);

    place(0, 0, mTabs, 5, 1);
    place(0, 1, mScrollArea, 5, 5).setPadding(2);
    place(0, 6, mResetKeysButton, 1, 1);
    place(2, 6, mAssignKeyButton, 1, 1);
    place(3, 6, mUnassignKeyButton, 1, 1);
    place(4, 6, mDefaultButton, 1, 1);

    int width = 600;
    if (config.getIntValue("screenwidth") >= 730)
        width += 100;

    setDimension(Rect(0, 0, width, 350));
}