mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-31 16:20:22 +00:00
Move mnemonic key as a property of ui::Widget
In this was we can process the text string just one time to remove the character preceded by '&' that will be finally acts as a mnemonic. This simplifies the rendering and text measure code too.
This commit is contained in:
parent
bb4faca1d1
commit
17151cddcd
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
@ -231,12 +231,14 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
|
|||||||
// Create the item
|
// Create the item
|
||||||
AppMenuItem* menuitem = new AppMenuItem(elem->Attribute("text"), command, params);
|
AppMenuItem* menuitem = new AppMenuItem(elem->Attribute("text"), command, params);
|
||||||
if (!menuitem)
|
if (!menuitem)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
/* has it a ID? */
|
menuitem->processMnemonicFromText();
|
||||||
|
|
||||||
|
// Has it a ID?
|
||||||
const char* id = elem->Attribute("id");
|
const char* id = elem->Attribute("id");
|
||||||
if (id) {
|
if (id) {
|
||||||
/* recent list menu */
|
// Recent list menu
|
||||||
if (strcmp(id, "recent_list") == 0) {
|
if (strcmp(id, "recent_list") == 0) {
|
||||||
m_recentListMenuitem = menuitem;
|
m_recentListMenuitem = menuitem;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ private:
|
|||||||
g->drawUIText(text(), fg, bg,
|
g->drawUIText(text(), fg, bg,
|
||||||
gfx::Point(
|
gfx::Point(
|
||||||
bounds.x + m_level*16 * guiscale(),
|
bounds.x + m_level*16 * guiscale(),
|
||||||
bounds.y + 2*guiscale()));
|
bounds.y + 2*guiscale()), 0);
|
||||||
|
|
||||||
if (m_key && !m_key->accels().empty()) {
|
if (m_key && !m_key->accels().empty()) {
|
||||||
std::string buf;
|
std::string buf;
|
||||||
@ -292,12 +292,13 @@ private:
|
|||||||
|
|
||||||
const char* label = "x";
|
const char* label = "x";
|
||||||
m_deleteButton->setBgColor(gfx::ColorNone);
|
m_deleteButton->setBgColor(gfx::ColorNone);
|
||||||
m_deleteButton->setBounds(gfx::Rect(
|
m_deleteButton->setBounds(
|
||||||
itemBounds.x + itemBounds.w + 2*guiscale(),
|
gfx::Rect(
|
||||||
itemBounds.y,
|
itemBounds.x + itemBounds.w + 2*guiscale(),
|
||||||
Graphics::measureUITextLength(
|
itemBounds.y,
|
||||||
label, font()) + 4*guiscale(),
|
Graphics::measureUITextLength(
|
||||||
itemBounds.h));
|
label, font()) + 4*guiscale(),
|
||||||
|
itemBounds.h));
|
||||||
m_deleteButton->setText(label);
|
m_deleteButton->setText(label);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
|
@ -138,8 +138,7 @@ void ButtonSet::Item::onPaint(ui::PaintEvent& ev)
|
|||||||
|
|
||||||
if (hasText()) {
|
if (hasText()) {
|
||||||
g->setFont(font());
|
g->setFont(font());
|
||||||
g->drawUIText(text(), fg, gfx::ColorNone, textRc.origin(),
|
g->drawUIText(text(), fg, gfx::ColorNone, textRc.origin(), 0);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +158,7 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
|
|||||||
if (isEnabled() && hasText()) {
|
if (isEnabled() && hasText()) {
|
||||||
KeyMessage* keymsg = static_cast<KeyMessage*>(msg);
|
KeyMessage* keymsg = static_cast<KeyMessage*>(msg);
|
||||||
bool mnemonicPressed = (msg->altPressed() &&
|
bool mnemonicPressed = (msg->altPressed() &&
|
||||||
mnemonicCharPressed(keymsg));
|
isMnemonicPressed(keymsg));
|
||||||
|
|
||||||
if (mnemonicPressed ||
|
if (mnemonicPressed ||
|
||||||
(hasFocus() && keymsg->scancode() == kKeySpace)) {
|
(hasFocus() && keymsg->scancode() == kKeySpace)) {
|
||||||
|
@ -230,7 +230,7 @@ void ColorButton::onPaint(PaintEvent& ev)
|
|||||||
|
|
||||||
gfx::Rect textrc;
|
gfx::Rect textrc;
|
||||||
getTextIconInfo(NULL, &textrc);
|
getTextIconInfo(NULL, &textrc);
|
||||||
g->drawUIText(text(), textcolor, gfx::ColorNone, textrc.origin());
|
g->drawUIText(text(), textcolor, gfx::ColorNone, textrc.origin(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorButton::onClick(Event& ev)
|
void ColorButton::onClick(Event& ev)
|
||||||
|
@ -947,7 +947,8 @@ void SkinTheme::paintCheckBox(PaintEvent& ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
drawText(g, NULL, ColorNone, ColorNone, widget, text, 0);
|
drawText(g, nullptr, ColorNone, ColorNone, widget, text, 0,
|
||||||
|
widget->mnemonic());
|
||||||
|
|
||||||
// Paint the icon
|
// Paint the icon
|
||||||
if (iconInterface)
|
if (iconInterface)
|
||||||
@ -1136,7 +1137,7 @@ void SkinTheme::drawEntryText(ui::Graphics* g, ui::Entry* widget)
|
|||||||
drawText(
|
drawText(
|
||||||
g, widget->getSuffix().c_str(),
|
g, widget->getSuffix().c_str(),
|
||||||
colors.entrySuffix(), ColorNone,
|
colors.entrySuffix(), ColorNone,
|
||||||
widget, sufBounds, 0);
|
widget, sufBounds, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1227,7 +1228,7 @@ void SkinTheme::paintListItem(ui::PaintEvent& ev)
|
|||||||
|
|
||||||
if (widget->hasText()) {
|
if (widget->hasText()) {
|
||||||
bounds.shrink(widget->border());
|
bounds.shrink(widget->border());
|
||||||
drawText(g, NULL, fg, bg, widget, bounds, 0);
|
drawText(g, nullptr, fg, bg, widget, bounds, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1298,7 +1299,8 @@ void SkinTheme::paintMenuItem(ui::PaintEvent& ev)
|
|||||||
Rect pos = bounds;
|
Rect pos = bounds;
|
||||||
if (!bar)
|
if (!bar)
|
||||||
pos.offset(widget->childSpacing()/2, 0);
|
pos.offset(widget->childSpacing()/2, 0);
|
||||||
drawText(g, NULL, fg, ColorNone, widget, pos, 0);
|
drawText(g, nullptr, fg, ColorNone, widget, pos, 0,
|
||||||
|
widget->mnemonic());
|
||||||
|
|
||||||
// For menu-box
|
// For menu-box
|
||||||
if (!bar) {
|
if (!bar) {
|
||||||
@ -1335,7 +1337,7 @@ void SkinTheme::paintMenuItem(ui::PaintEvent& ev)
|
|||||||
std::string buf = appMenuItem->key()->accels().front().toString();
|
std::string buf = appMenuItem->key()->accels().front().toString();
|
||||||
|
|
||||||
widget->setAlign(RIGHT | MIDDLE);
|
widget->setAlign(RIGHT | MIDDLE);
|
||||||
drawText(g, buf.c_str(), fg, ColorNone, widget, pos, 0);
|
drawText(g, buf.c_str(), fg, ColorNone, widget, pos, 0, 0);
|
||||||
widget->setAlign(old_align);
|
widget->setAlign(old_align);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1375,7 +1377,7 @@ void SkinTheme::paintRadioButton(PaintEvent& ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
drawText(g, NULL, ColorNone, ColorNone, widget, text, 0);
|
drawText(g, nullptr, ColorNone, ColorNone, widget, text, 0, widget->mnemonic());
|
||||||
|
|
||||||
// Icon
|
// Icon
|
||||||
if (iconInterface)
|
if (iconInterface)
|
||||||
@ -1417,9 +1419,9 @@ void SkinTheme::paintSeparator(ui::PaintEvent& ev)
|
|||||||
bounds.y + bounds.h/2 - h/2,
|
bounds.y + bounds.h/2 - h/2,
|
||||||
widget->textWidth(), h);
|
widget->textWidth(), h);
|
||||||
|
|
||||||
drawText(g, NULL,
|
drawText(g, nullptr,
|
||||||
colors.separatorLabel(), BGCOLOR,
|
colors.separatorLabel(), BGCOLOR,
|
||||||
widget, r, 0);
|
widget, r, 0, widget->mnemonic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1522,18 +1524,18 @@ void SkinTheme::paintSlider(PaintEvent& ev)
|
|||||||
{
|
{
|
||||||
IntersectClip clip(g, Rect(rc.x, rc.y, x-rc.x, rc.h));
|
IntersectClip clip(g, Rect(rc.x, rc.y, x-rc.x, rc.h));
|
||||||
if (clip) {
|
if (clip) {
|
||||||
drawText(g, NULL,
|
drawText(g, nullptr,
|
||||||
colors.sliderFullText(), ColorNone,
|
colors.sliderFullText(), ColorNone,
|
||||||
widget, rc, 0);
|
widget, rc, 0, widget->mnemonic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
IntersectClip clip(g, Rect(x+1, rc.y, rc.w-(x-rc.x+1), rc.h));
|
IntersectClip clip(g, Rect(x+1, rc.y, rc.w-(x-rc.x+1), rc.h));
|
||||||
if (clip) {
|
if (clip) {
|
||||||
drawText(g, NULL,
|
drawText(g, nullptr,
|
||||||
colors.sliderEmptyText(),
|
colors.sliderEmptyText(),
|
||||||
ColorNone, widget, rc, 0);
|
ColorNone, widget, rc, 0, widget->mnemonic());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1816,7 +1818,7 @@ gfx::Color SkinTheme::getWidgetBgColor(Widget* widget)
|
|||||||
|
|
||||||
void SkinTheme::drawText(Graphics* g, const char *t, gfx::Color fg_color, gfx::Color bg_color,
|
void SkinTheme::drawText(Graphics* g, const char *t, gfx::Color fg_color, gfx::Color bg_color,
|
||||||
Widget* widget, const Rect& rc,
|
Widget* widget, const Rect& rc,
|
||||||
int selected_offset)
|
int selected_offset, int mnemonic)
|
||||||
{
|
{
|
||||||
if (t || widget->hasText()) {
|
if (t || widget->hasText()) {
|
||||||
Rect textrc;
|
Rect textrc;
|
||||||
@ -1869,18 +1871,22 @@ void SkinTheme::drawText(Graphics* g, const char *t, gfx::Color fg_color, gfx::C
|
|||||||
if (clip) {
|
if (clip) {
|
||||||
if (!widget->isEnabled()) {
|
if (!widget->isEnabled()) {
|
||||||
// Draw white part
|
// Draw white part
|
||||||
g->drawUIText(t,
|
g->drawUIText(
|
||||||
|
t,
|
||||||
colors.background(),
|
colors.background(),
|
||||||
gfx::ColorNone,
|
gfx::ColorNone,
|
||||||
textrc.origin() + Point(guiscale(), guiscale()));
|
textrc.origin() + Point(guiscale(), guiscale()),
|
||||||
|
mnemonic);
|
||||||
}
|
}
|
||||||
|
|
||||||
g->drawUIText(t,
|
g->drawUIText(
|
||||||
|
t,
|
||||||
(!widget->isEnabled() ?
|
(!widget->isEnabled() ?
|
||||||
colors.disabled():
|
colors.disabled():
|
||||||
(gfx::geta(fg_color) > 0 ? fg_color :
|
(gfx::geta(fg_color) > 0 ? fg_color :
|
||||||
colors.text())),
|
colors.text())),
|
||||||
bg_color, textrc.origin());
|
bg_color, textrc.origin(),
|
||||||
|
mnemonic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ namespace app {
|
|||||||
gfx::Color getWidgetBgColor(ui::Widget* widget);
|
gfx::Color getWidgetBgColor(ui::Widget* widget);
|
||||||
void drawText(ui::Graphics* g, const char *t, gfx::Color fg_color, gfx::Color bg_color,
|
void drawText(ui::Graphics* g, const char *t, gfx::Color fg_color, gfx::Color bg_color,
|
||||||
ui::Widget* widget, const gfx::Rect& rc,
|
ui::Widget* widget, const gfx::Rect& rc,
|
||||||
int selected_offset);
|
int selected_offset, int mnemonic);
|
||||||
void drawEntryText(ui::Graphics* g, ui::Entry* widget);
|
void drawEntryText(ui::Graphics* g, ui::Entry* widget);
|
||||||
|
|
||||||
void paintIcon(ui::Widget* widget, ui::Graphics* g, ui::IButtonIcon* iconInterface, int x, int y);
|
void paintIcon(ui::Widget* widget, ui::Graphics* g, ui::IButtonIcon* iconInterface, int x, int y);
|
||||||
|
@ -475,8 +475,9 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Was the widget created?
|
// Was the widget created?
|
||||||
if (widget)
|
if (widget) {
|
||||||
fillWidgetWithXmlElementAttributesWithChildren(elem, root, widget);
|
fillWidgetWithXmlElementAttributesWithChildren(elem, root, widget);
|
||||||
|
}
|
||||||
|
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
@ -587,6 +588,9 @@ void WidgetLoader::fillWidgetWithXmlElementAttributes(const TiXmlElement* elem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign widget mnemonic from the character preceded by a '&'
|
||||||
|
widget->processMnemonicFromText();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetLoader::fillWidgetWithXmlElementAttributesWithChildren(const TiXmlElement* elem, ui::Widget* root, ui::Widget* widget)
|
void WidgetLoader::fillWidgetWithXmlElementAttributesWithChildren(const TiXmlElement* elem, ui::Widget* root, ui::Widget* widget)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// Aseprite UI Library
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -158,6 +158,7 @@ void Alert::processString(std::string& buf)
|
|||||||
else if (button) {
|
else if (button) {
|
||||||
char buttonId[256];
|
char buttonId[256];
|
||||||
Button* button_widget = new Button(item);
|
Button* button_widget = new Button(item);
|
||||||
|
button_widget->processMnemonicFromText();
|
||||||
button_widget->setMinSize(gfx::Size(60*guiscale(), 0));
|
button_widget->setMinSize(gfx::Size(60*guiscale(), 0));
|
||||||
m_buttons.push_back(button_widget);
|
m_buttons.push_back(button_widget);
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ bool ButtonBase::onProcessMessage(Message* msg)
|
|||||||
if (isEnabled()) {
|
if (isEnabled()) {
|
||||||
bool mnemonicPressed =
|
bool mnemonicPressed =
|
||||||
((msg->altPressed() || msg->cmdPressed()) &&
|
((msg->altPressed() || msg->cmdPressed()) &&
|
||||||
mnemonicCharPressed(keymsg));
|
isMnemonicPressed(keymsg));
|
||||||
|
|
||||||
// For kButtonWidget
|
// For kButtonWidget
|
||||||
if (m_behaviorType == kButtonWidget) {
|
if (m_behaviorType == kButtonWidget) {
|
||||||
|
@ -237,11 +237,11 @@ namespace {
|
|||||||
class DrawUITextDelegate : public she::DrawTextDelegate {
|
class DrawUITextDelegate : public she::DrawTextDelegate {
|
||||||
public:
|
public:
|
||||||
DrawUITextDelegate(she::Surface* surface,
|
DrawUITextDelegate(she::Surface* surface,
|
||||||
she::Font* font, const bool drawUnderscore)
|
she::Font* font, const int mnemonic)
|
||||||
: m_surface(surface)
|
: m_surface(surface)
|
||||||
, m_font(font)
|
, m_font(font)
|
||||||
, m_drawUnderscore(drawUnderscore)
|
, m_mnemonic(std::tolower(mnemonic))
|
||||||
, m_underscoreNext(false) {
|
, m_underscoreColor(gfx::ColorNone) {
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Rect bounds() const { return m_bounds; }
|
gfx::Rect bounds() const { return m_bounds; }
|
||||||
@ -253,19 +253,15 @@ public:
|
|||||||
gfx::Color& bg,
|
gfx::Color& bg,
|
||||||
bool& drawChar,
|
bool& drawChar,
|
||||||
bool& moveCaret) override {
|
bool& moveCaret) override {
|
||||||
if (m_underscoreNext)
|
|
||||||
m_underscoreColor = fg;
|
|
||||||
|
|
||||||
if (!m_surface)
|
if (!m_surface)
|
||||||
drawChar = false;
|
drawChar = false;
|
||||||
|
else {
|
||||||
moveCaret = true;
|
if (m_mnemonic && std::tolower(chr) == m_mnemonic) {
|
||||||
if (chr == '&') { // TODO change this with other character, maybe '_' or configurable
|
m_underscoreColor = fg;
|
||||||
auto it2 = it;
|
m_mnemonic = 0; // Just one time
|
||||||
++it2;
|
}
|
||||||
if (it2 != end && *it2 != '&') {
|
else {
|
||||||
m_underscoreNext = true;
|
m_underscoreColor = gfx::ColorNone;
|
||||||
moveCaret = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,40 +272,36 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void postDrawChar(const gfx::Rect& charBounds) override {
|
void postDrawChar(const gfx::Rect& charBounds) override {
|
||||||
if (m_underscoreNext) {
|
if (!gfx::is_transparent(m_underscoreColor)) {
|
||||||
m_underscoreNext = false;
|
// TODO underscore height = guiscale() should be configurable from ui::Theme
|
||||||
if (m_drawUnderscore) {
|
int dy = 0;
|
||||||
// TODO underscore height = guiscale() should be configurable from ui::Theme
|
if (m_font->type() == she::FontType::kTrueType) // TODO use other method to locate the underline
|
||||||
int dy = 0;
|
dy += guiscale();
|
||||||
if (m_font->type() == she::FontType::kTrueType) // TODO use other method to locate the underline
|
gfx::Rect underscoreBounds(charBounds.x, charBounds.y+charBounds.h+dy,
|
||||||
dy += guiscale();
|
charBounds.w, guiscale());
|
||||||
gfx::Rect underscoreBounds(charBounds.x, charBounds.y+charBounds.h+dy,
|
m_surface->fillRect(m_underscoreColor, underscoreBounds);
|
||||||
charBounds.w, guiscale());
|
m_bounds |= underscoreBounds;
|
||||||
m_surface->fillRect(m_underscoreColor, underscoreBounds);
|
|
||||||
m_bounds |= underscoreBounds;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
she::Surface* m_surface;
|
she::Surface* m_surface;
|
||||||
she::Font* m_font;
|
she::Font* m_font;
|
||||||
bool m_drawUnderscore;
|
int m_mnemonic;
|
||||||
bool m_underscoreNext;
|
|
||||||
gfx::Color m_underscoreColor;
|
gfx::Color m_underscoreColor;
|
||||||
gfx::Rect m_bounds;
|
gfx::Rect m_bounds;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt,
|
void Graphics::drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg,
|
||||||
bool drawUnderscore)
|
const gfx::Point& pt, const int mnemonic)
|
||||||
{
|
{
|
||||||
she::SurfaceLock lock(m_surface);
|
she::SurfaceLock lock(m_surface);
|
||||||
int x = m_dx+pt.x;
|
int x = m_dx+pt.x;
|
||||||
int y = m_dy+pt.y;
|
int y = m_dy+pt.y;
|
||||||
|
|
||||||
DrawUITextDelegate delegate(m_surface, m_font, drawUnderscore);
|
DrawUITextDelegate delegate(m_surface, m_font, mnemonic);
|
||||||
she::draw_text(m_surface, m_font,
|
she::draw_text(m_surface, m_font,
|
||||||
base::utf8_const_iterator(str.begin()),
|
base::utf8_const_iterator(str.begin()),
|
||||||
base::utf8_const_iterator(str.end()),
|
base::utf8_const_iterator(str.end()),
|
||||||
@ -318,7 +310,8 @@ void Graphics::drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg,
|
|||||||
dirty(delegate.bounds());
|
dirty(delegate.bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::drawAlignedUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, int align)
|
void Graphics::drawAlignedUIText(const std::string& str, gfx::Color fg, gfx::Color bg,
|
||||||
|
const gfx::Rect& rc, const int align)
|
||||||
{
|
{
|
||||||
doUIStringAlgorithm(str, fg, bg, rc, align, true);
|
doUIStringAlgorithm(str, fg, bg, rc, align, true);
|
||||||
}
|
}
|
||||||
@ -333,7 +326,7 @@ gfx::Size Graphics::measureUIText(const std::string& str)
|
|||||||
// static
|
// static
|
||||||
int Graphics::measureUITextLength(const std::string& str, she::Font* font)
|
int Graphics::measureUITextLength(const std::string& str, she::Font* font)
|
||||||
{
|
{
|
||||||
DrawUITextDelegate delegate(nullptr, font, false);
|
DrawUITextDelegate delegate(nullptr, font, 0);
|
||||||
she::draw_text(nullptr, font,
|
she::draw_text(nullptr, font,
|
||||||
base::utf8_const_iterator(str.begin()),
|
base::utf8_const_iterator(str.begin()),
|
||||||
base::utf8_const_iterator(str.end()),
|
base::utf8_const_iterator(str.end()),
|
||||||
|
@ -86,13 +86,9 @@ namespace ui {
|
|||||||
const base::utf8_const_iterator& end,
|
const base::utf8_const_iterator& end,
|
||||||
gfx::Color fg, gfx::Color bg, const gfx::Point& pt,
|
gfx::Color fg, gfx::Color bg, const gfx::Point& pt,
|
||||||
she::DrawTextDelegate* delegate);
|
she::DrawTextDelegate* delegate);
|
||||||
|
void drawText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt);
|
||||||
void drawText(const std::string& str, gfx::Color fg, gfx::Color bg,
|
void drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt, const int mnemonic);
|
||||||
const gfx::Point& pt);
|
void drawAlignedUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, const int align);
|
||||||
void drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg,
|
|
||||||
const gfx::Point& pt, bool drawUnderscore = true);
|
|
||||||
void drawAlignedUIText(const std::string& str, gfx::Color fg, gfx::Color bg,
|
|
||||||
const gfx::Rect& rc, int align);
|
|
||||||
|
|
||||||
gfx::Size measureUIText(const std::string& str);
|
gfx::Size measureUIText(const std::string& str);
|
||||||
static int measureUITextLength(const std::string& str, she::Font* font);
|
static int measureUITextLength(const std::string& str, she::Font* font);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite UI Library
|
// Aseprite UI Library
|
||||||
// Copyright (C) 2001-2016 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -1218,7 +1218,7 @@ static MenuItem* check_for_letter(Menu* menu, const KeyMessage* keymsg)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
MenuItem* menuitem = static_cast<MenuItem*>(child);
|
MenuItem* menuitem = static_cast<MenuItem*>(child);
|
||||||
if (menuitem->mnemonicCharPressed(keymsg))
|
if (menuitem->isMnemonicPressed(keymsg))
|
||||||
return menuitem;
|
return menuitem;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -152,7 +152,8 @@ void Theme::paintLayer(Graphics* g, Widget* widget,
|
|||||||
layer.color(),
|
layer.color(),
|
||||||
gfx::ColorNone,
|
gfx::ColorNone,
|
||||||
gfx::Point(rc.x+rc.w/2-textSize.w/2,
|
gfx::Point(rc.x+rc.w/2-textSize.w/2,
|
||||||
rc.y+rc.h/2-textSize.h/2), true);
|
rc.y+rc.h/2-textSize.h/2),
|
||||||
|
widget->mnemonic());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ Widget::Widget(WidgetType type)
|
|||||||
, m_bounds(0, 0, 0, 0)
|
, m_bounds(0, 0, 0, 0)
|
||||||
, m_parent(nullptr)
|
, m_parent(nullptr)
|
||||||
, m_sizeHint(nullptr)
|
, m_sizeHint(nullptr)
|
||||||
|
, m_mnemonic(0)
|
||||||
, m_minSize(0, 0)
|
, m_minSize(0, 0)
|
||||||
, m_maxSize(INT_MAX, INT_MAX)
|
, m_maxSize(INT_MAX, INT_MAX)
|
||||||
, m_childSpacing(0)
|
, m_childSpacing(0)
|
||||||
@ -1260,12 +1261,12 @@ bool Widget::offerCapture(ui::MouseMessage* mouseMsg, int widget_type)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::hasFocus()
|
bool Widget::hasFocus() const
|
||||||
{
|
{
|
||||||
return hasFlags(HAS_FOCUS);
|
return hasFlags(HAS_FOCUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::hasMouse()
|
bool Widget::hasMouse() const
|
||||||
{
|
{
|
||||||
return hasFlags(HAS_MOUSE);
|
return hasFlags(HAS_MOUSE);
|
||||||
}
|
}
|
||||||
@ -1275,24 +1276,43 @@ bool Widget::hasMouseOver()
|
|||||||
return (this == pick(get_mouse_position()));
|
return (this == pick(get_mouse_position()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::hasCapture()
|
bool Widget::hasCapture() const
|
||||||
{
|
{
|
||||||
return hasFlags(HAS_CAPTURE);
|
return hasFlags(HAS_CAPTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Widget::mnemonicChar() const
|
void Widget::setMnemonic(int mnemonic)
|
||||||
{
|
{
|
||||||
if (hasText()) {
|
m_mnemonic = mnemonic;
|
||||||
for (int c=0; m_text[c]; ++c)
|
|
||||||
if ((m_text[c] == '&') && (m_text[c+1] != '&'))
|
|
||||||
return std::tolower(m_text[c+1]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Widget::mnemonicCharPressed(const KeyMessage* keyMsg) const
|
void Widget::processMnemonicFromText(int escapeChar)
|
||||||
{
|
{
|
||||||
int chr = mnemonicChar();
|
std::string newText;
|
||||||
|
if (!m_text.empty())
|
||||||
|
newText.reserve(m_text.size());
|
||||||
|
|
||||||
|
for (base::utf8_const_iterator
|
||||||
|
it(m_text.begin()),
|
||||||
|
end(m_text.end()); it != end; ++it) {
|
||||||
|
if (*it == escapeChar) {
|
||||||
|
++it;
|
||||||
|
if (it == end) {
|
||||||
|
break; // Ill-formed string (it ends with escape character)
|
||||||
|
}
|
||||||
|
else if (*it != escapeChar) {
|
||||||
|
setMnemonic(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newText.push_back(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(newText);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Widget::isMnemonicPressed(const KeyMessage* keyMsg) const
|
||||||
|
{
|
||||||
|
int chr = std::tolower(mnemonic());
|
||||||
return
|
return
|
||||||
((chr) &&
|
((chr) &&
|
||||||
((chr == std::tolower(keyMsg->unicodeChar())) ||
|
((chr == std::tolower(keyMsg->unicodeChar())) ||
|
||||||
|
@ -339,10 +339,10 @@ namespace ui {
|
|||||||
void captureMouse();
|
void captureMouse();
|
||||||
void releaseMouse();
|
void releaseMouse();
|
||||||
|
|
||||||
bool hasFocus();
|
bool hasFocus() const;
|
||||||
bool hasMouse();
|
bool hasMouse() const;
|
||||||
bool hasMouseOver();
|
bool hasMouseOver();
|
||||||
bool hasCapture();
|
bool hasCapture() const;
|
||||||
|
|
||||||
// Offer the capture to widgets of the given type. Returns true if
|
// Offer the capture to widgets of the given type. Returns true if
|
||||||
// the capture was passed to other widget.
|
// the capture was passed to other widget.
|
||||||
@ -350,10 +350,15 @@ namespace ui {
|
|||||||
|
|
||||||
// Returns lower-case letter that represet the mnemonic of the widget
|
// Returns lower-case letter that represet the mnemonic of the widget
|
||||||
// (the underscored character, i.e. the letter after & symbol).
|
// (the underscored character, i.e. the letter after & symbol).
|
||||||
int mnemonicChar() const;
|
int mnemonic() const { return m_mnemonic; }
|
||||||
|
void setMnemonic(int mnemonic);
|
||||||
|
|
||||||
|
// Assigns mnemonic from the character preceded by the given
|
||||||
|
// escapeChar ('&' by default).
|
||||||
|
void processMnemonicFromText(int escapeChar = '&');
|
||||||
|
|
||||||
// Returns true if the mnemonic character is pressed.
|
// Returns true if the mnemonic character is pressed.
|
||||||
bool mnemonicCharPressed(const ui::KeyMessage* keyMsg) const;
|
bool isMnemonicPressed(const ui::KeyMessage* keyMsg) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// ===============================================================
|
// ===============================================================
|
||||||
@ -399,6 +404,7 @@ namespace ui {
|
|||||||
WidgetsList m_children; // Sub-widgets
|
WidgetsList m_children; // Sub-widgets
|
||||||
Widget* m_parent; // Who is the parent?
|
Widget* m_parent; // Who is the parent?
|
||||||
gfx::Size* m_sizeHint;
|
gfx::Size* m_sizeHint;
|
||||||
|
int m_mnemonic; // Keyboard shortcut to access this widget like Alt+mnemonic
|
||||||
|
|
||||||
// Widget size limits
|
// Widget size limits
|
||||||
gfx::Size m_minSize, m_maxSize;
|
gfx::Size m_minSize, m_maxSize;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user