implement combobox and do some ui rework

This commit is contained in:
Eduardo Bart
2012-01-04 08:26:58 -02:00
parent 02ae3ac616
commit b8150d160e
48 changed files with 413 additions and 592 deletions

View File

@@ -25,8 +25,6 @@
#include "uimanager.h"
#include "uiwidget.h"
#include "uibutton.h"
#include "uilabel.h"
#include "uilineedit.h"
#include "uiwindow.h"
#include "uiframecounter.h"

View File

@@ -1,72 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uibutton.h"
#include <framework/graphics/borderimage.h>
#include <framework/graphics/font.h>
#include <framework/otml/otmlnode.h>
#include <framework/luascript/luainterface.h>
#include <framework/graphics/graphics.h>
#include <framework/graphics/texture.h>
#include <framework/graphics/texturemanager.h>
UIButton::UIButton()
{
m_focusable = false;
}
void UIButton::render()
{
UIWidget::render();
if(m_icon) {
Rect iconRect;
iconRect.resize(m_icon->getSize());
iconRect.moveCenter(m_rect.center());
g_painter.drawTexturedRect(iconRect, m_icon);
}
Rect textRect = m_rect;
textRect.translate(m_textOffset);
m_font->renderText(m_text, textRect, Fw::AlignCenter, m_foregroundColor);
}
void UIButton::onStyleApply(const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleNode);
for(OTMLNodePtr node : styleNode->children()) {
if(node->tag() == "text-offset")
m_textOffset = node->value<Point>();
else if(node->tag() == "text")
m_text = node->value();
else if(node->tag() == "icon")
m_icon = g_textures.getTexture(node->value());
}
}
void UIButton::onMouseRelease(const Point& mousePos, Fw::MouseButton button)
{
if(isPressed() && getRect().contains(mousePos)) {
callLuaField("onClick");
}
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UIBUTTON_H
#define UIBUTTON_H
#include "uiwidget.h"
class UIButton : public UIWidget
{
public:
UIButton();
virtual void render();
void setText(const std::string& text) { m_text = text; }
std::string getText() const { return m_text; }
UIButtonPtr asUIButton() { return std::static_pointer_cast<UIButton>(shared_from_this()); }
protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);
Point m_textOffset;
TexturePtr m_icon;
std::string m_text;
};
#endif

View File

@@ -58,9 +58,9 @@ void UICheckBox::onMouseRelease(const Point& mousePos, Fw::MouseButton button)
setChecked(!isChecked());
}
void UICheckBox::onStyleApply(const OTMLNodePtr& styleNode)
void UICheckBox::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleNode);
UIWidget::onStyleApply(styleName, styleNode);
for(OTMLNodePtr node : styleNode->children()) {
if(node->tag() == "text-offset")

View File

@@ -40,7 +40,7 @@ public:
UICheckBoxPtr asUICheckBox() { return std::static_pointer_cast<UICheckBox>(shared_from_this()); }
protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);
std::string m_text;

View File

@@ -50,9 +50,9 @@ void UIFrameCounter::render()
m_font->renderText(m_fpsText, m_rect, m_align, Fw::white);
}
void UIFrameCounter::onStyleApply(const OTMLNodePtr& styleNode)
void UIFrameCounter::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleNode);
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "align")

View File

@@ -36,7 +36,7 @@ public:
int getFrameCount() { return m_frameCount; }
protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
private:
Fw::AlignmentFlag m_align;

View File

@@ -1,75 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "uilabel.h"
#include "uitranslator.h"
#include <framework/graphics/font.h>
#include <framework/otml/otmlnode.h>
UILabel::UILabel()
{
m_focusable = false;
m_phantom = true;
m_textAlign = Fw::AlignLeft;
}
void UILabel::render()
{
UIWidget::render();
Rect textRect = m_rect;
textRect.setTopLeft(textRect.topLeft() + m_textOffset);
m_font->renderText(m_text, textRect, m_textAlign, m_foregroundColor);
}
void UILabel::setText(const std::string& text)
{
m_text = text;
// auto resize
if(!m_fixedSize && !m_rect.isValid()) {
Size textSize = m_font->calculateTextRectSize(m_text);
if(m_rect.width() <= 0)
m_rect.setWidth(textSize.width());
if(m_rect.height() <= 0)
m_rect.setHeight(textSize.height());
}
}
void UILabel::resizeToText()
{
resize(m_font->calculateTextRectSize(m_text));
}
void UILabel::onStyleApply(const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "text")
setText(node->value());
else if(node->tag() == "text-align")
setTextAlign(Fw::translateAlignment(node->value()));
else if(node->tag() == "text-offset") {
setTextOffset(node->value<Point>());
}
}
}

View File

@@ -1,53 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UILABEL_H
#define UILABEL_H
#include "uiwidget.h"
class UILabel : public UIWidget
{
public:
UILabel();
virtual void render();
void resizeToText();
void setText(const std::string& text);
void setTextAlign(Fw::AlignmentFlag align) { m_textAlign = align; }
void setTextOffset(const Point& offset) { m_textOffset = offset; }
std::string getText() const { return m_text; }
Fw::AlignmentFlag getTextAlign() const { return m_textAlign; }
Point getTextOffset() const { return m_textOffset; }
protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode);
private:
std::string m_text;
Point m_textOffset;
Fw::AlignmentFlag m_textAlign;
};
#endif

View File

@@ -29,8 +29,8 @@
UILineEdit::UILineEdit()
{
m_align = Fw::AlignLeftCenter;
m_cursorPos = 0;
m_textAlign = Fw::AlignLeftCenter;
m_startRenderPos = 0;
m_textHorizontalMargin = 0;
m_textHidden = false;
@@ -38,9 +38,12 @@ UILineEdit::UILineEdit()
blinkCursor();
}
void UILineEdit::render()
void UILineEdit::renderSelf()
{
UIWidget::render();
drawBackground(m_rect);
drawBorder(m_rect);
drawImage(m_rect);
drawIcon(m_rect);
//TODO: text rendering could be much optimized by using vertex buffer or caching the render into a texture
@@ -81,7 +84,7 @@ void UILineEdit::update()
// map glyphs positions
Size textBoxSize;
const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(text, m_align, &textBoxSize);
const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize);
const Rect *glyphsTextureCoords = m_font->getGlyphsTextureCoords();
const Size *glyphsSize = m_font->getGlyphsSize();
int glyph;
@@ -141,16 +144,16 @@ void UILineEdit::update()
textScreenCoords.addRight(-m_textHorizontalMargin);
m_drawArea = textScreenCoords;
if(m_align & Fw::AlignBottom) {
if(m_textAlign & Fw::AlignBottom) {
m_drawArea.translate(0, textScreenCoords.height() - textBoxSize.height());
} else if(m_align & Fw::AlignVerticalCenter) {
} else if(m_textAlign & Fw::AlignVerticalCenter) {
m_drawArea.translate(0, (textScreenCoords.height() - textBoxSize.height()) / 2);
} else { // AlignTop
}
if(m_align & Fw::AlignRight) {
if(m_textAlign & Fw::AlignRight) {
m_drawArea.translate(textScreenCoords.width() - textBoxSize.width(), 0);
} else if(m_align & Fw::AlignHorizontalCenter) {
} else if(m_textAlign & Fw::AlignHorizontalCenter) {
m_drawArea.translate((textScreenCoords.width() - textBoxSize.width()) / 2, 0);
} else { // AlignLeft
@@ -169,17 +172,17 @@ void UILineEdit::update()
Rect glyphTextureCoords = glyphsTextureCoords[glyph];
// first translate to align position
if(m_align & Fw::AlignBottom) {
if(m_textAlign & Fw::AlignBottom) {
glyphScreenCoords.translate(0, textScreenCoords.height() - textBoxSize.height());
} else if(m_align & Fw::AlignVerticalCenter) {
} else if(m_textAlign & Fw::AlignVerticalCenter) {
glyphScreenCoords.translate(0, (textScreenCoords.height() - textBoxSize.height()) / 2);
} else { // AlignTop
// nothing to do
}
if(m_align & Fw::AlignRight) {
if(m_textAlign & Fw::AlignRight) {
glyphScreenCoords.translate(textScreenCoords.width() - textBoxSize.width(), 0);
} else if(m_align & Fw::AlignHorizontalCenter) {
} else if(m_textAlign & Fw::AlignHorizontalCenter) {
glyphScreenCoords.translate((textScreenCoords.width() - textBoxSize.width()) / 2, 0);
} else { // AlignLeft
// nothing to do
@@ -225,38 +228,12 @@ void UILineEdit::update()
}
}
void UILineEdit::setFont(const FontPtr& font)
void UILineEdit::setTextHorizontalMargin(int margin)
{
if(m_font != font) {
m_font = font;
update();
}
}
void UILineEdit::setText(const std::string& text)
{
if(m_text != text) {
m_text = text;
m_cursorPos = text.length();
blinkCursor();
update();
}
}
void UILineEdit::setTextHidden(bool hidden)
{
m_textHidden = true;
m_textHorizontalMargin = margin;
update();
}
void UILineEdit::setAlign(Fw::AlignmentFlag align)
{
if(m_align != align) {
m_align = align;
update();
}
}
void UILineEdit::setCursorPos(int pos)
{
if(pos != m_cursorPos) {
@@ -280,6 +257,17 @@ void UILineEdit::setCursorEnabled(bool enable)
update();
}
void UILineEdit::setTextHidden(bool hidden)
{
m_textHidden = true;
update();
}
void UILineEdit::setAlwaysActive(bool enable)
{
m_alwaysActive = enable;
}
void UILineEdit::appendText(std::string text)
{
if(m_cursorPos >= 0) {
@@ -373,21 +361,34 @@ std::string UILineEdit::getDisplayedText()
return m_text;
}
void UILineEdit::onStyleApply(const OTMLNodePtr& styleNode)
void UILineEdit::onTextChange(const std::string& text)
{
UIWidget::onStyleApply(styleNode);
m_cursorPos = text.length();
blinkCursor();
update();
UIWidget::onTextChange(text);
}
void UILineEdit::onFontChange(const std::string& font)
{
update();
UIWidget::onFontChange(font);
}
void UILineEdit::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleName, styleNode);
for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "text") {
setText(node->value());
setCursorPos(m_text.length());
} else if(node->tag() == "text-hidden") {
} else if(node->tag() == "text-hidden")
setTextHidden(node->value<bool>());
} else if(node->tag() == "text-margin") {
m_textHorizontalMargin = node->value<int>();
} else if(node->tag() == "always-active") {
m_alwaysActive = true;
}
else if(node->tag() == "text-margin")
setTextHorizontalMargin(node->value<int>());
else if(node->tag() == "always-active")
setAlwaysActive(node->value<bool>());
}
}

View File

@@ -30,30 +30,35 @@ class UILineEdit : public UIWidget
public:
UILineEdit();
virtual void render();
virtual void renderSelf();
private:
void update();
void setText(const std::string& text);
void setTextHidden(bool hidden);
void setAlign(Fw::AlignmentFlag align);
public:
void setTextHorizontalMargin(int margin);
void setCursorPos(int pos);
void setCursorEnabled(bool enable = true);
void setCursorEnabled(bool enable);
void setTextHidden(bool hidden);
void setAlwaysActive(bool enable);
void clearText() { setText(""); }
void moveCursor(bool right);
void appendText(std::string text);
void appendCharacter(char c);
void removeCharacter(bool right);
void setFont(const FontPtr& font);
std::string getText() const { return m_text; }
std::string getDisplayedText();
int getTextPos(Point pos);
int getCursorPos() const { return m_cursorPos; }
int getTextHorizontalMargin() { return m_textHorizontalMargin; }
int getCursorPos() { return m_cursorPos; }
bool isCursorEnabled() { return m_cursorPos != -1; }
bool isAlwaysActive() { return m_alwaysActive; }
bool isTextHidden() { return m_textHidden; }
protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void onTextChange(const std::string& text);
virtual void onFontChange(const std::string& font);
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
@@ -62,9 +67,7 @@ protected:
private:
void blinkCursor();
std::string m_text;
Rect m_drawArea;
Fw::AlignmentFlag m_align;
int m_cursorPos;
Point m_startInternalPos;
int m_startRenderPos;

View File

@@ -54,7 +54,7 @@ void UIVerticalLayout::update()
if(m_alignBottom)
std::reverse(widgets.begin(), widgets.end());
Point pos = (m_alignBottom) ? parentWidget->getRect().bottomLeft() : parentWidget->getPosition();
Point pos = (m_alignBottom) ? parentWidget->getRect().bottomLeft() : parentWidget->getPos();
int prefferedHeight = 0;
int gap;

View File

@@ -33,6 +33,7 @@
#include <framework/otml/otmlnode.h>
#include <framework/graphics/graphics.h>
#include <framework/platform/platformwindow.h>
#include <framework/graphics/texturemanager.h>
UIWidget::UIWidget()
{
@@ -41,6 +42,10 @@ UIWidget::UIWidget()
m_font = g_fonts.getDefaultFont();
m_opacity = 255;
m_marginTop = m_marginRight = m_marginBottom = m_marginLeft = 0;
//m_backgroundColor = Fw::alpha;
m_backgroundColor = Fw::white;
m_foregroundColor = Fw::white;
m_textAlign = Fw::AlignCenter;
// generate an unique id, this is need because anchored layouts find widgets by id
static unsigned long id = 1;
@@ -74,11 +79,12 @@ void UIWidget::render()
void UIWidget::renderSelf()
{
// draw background
if(m_image) {
g_painter.setColor(m_backgroundColor);
m_image->draw(m_rect);
}
// draw style components in order
drawBackground(m_rect);
drawBorder(m_rect);
drawImage(m_rect);
drawIcon(m_rect);
drawText(m_rect);
}
void UIWidget::renderChildren()
@@ -86,7 +92,10 @@ void UIWidget::renderChildren()
// draw children
for(const UIWidgetPtr& child : m_children) {
// render only visible children with a valid rect inside our rect
if(child->isExplicitlyVisible() && child->getRect().isValid() && child->getRect().intersects(m_rect)) {
if(child->isExplicitlyVisible() &&
child->getRect().isValid() &&
child->getRect().intersects(m_rect) &&
child->getOpacity() > 0) {
// store current graphics opacity
int oldOpacity = g_painter.getOpacity();
@@ -99,13 +108,63 @@ void UIWidget::renderChildren()
// debug draw box
//g_painter.setColor(Fw::green);
//g_painter.drawBoundingRect(child->getRect());
//g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Fw::red);
//g_fonts.getDefaultFont()->renderText(child->getId(), child->getPos() + Point(2, 0), Fw::red);
g_painter.setOpacity(oldOpacity);
}
}
}
void UIWidget::drawBackground(const Rect& screenCoords)
{
/*
if(m_backgroundColor.a() > 0) {
g_painter.setColor(m_backgroundColor);
g_painter.drawFilledRect(screenCoords);
//g_painter.drawFilledRect(screenCoords.expanded(-m_borderWidth));
}
*/
}
void UIWidget::drawBorder(const Rect& screenCoords)
{
/*
if(m_borderWidth > 0 && m_borderColor.a() > 0) {
g_painter.bindColor(m_borderColor);
g_painter.drawBoundingRect(screenCoords, m_borderWidth);
}
*/
}
void UIWidget::drawImage(const Rect& screenCoords)
{
if(m_image) {
g_painter.setColor(m_backgroundColor);
m_image->draw(screenCoords);
}
}
void UIWidget::drawIcon(const Rect& screenCoords)
{
if(m_icon) {
Rect iconRect;
iconRect.resize(m_icon->getSize());
iconRect.moveCenter(screenCoords.center());
g_painter.setColor(Fw::white);
g_painter.drawTexturedRect(iconRect, m_icon);
}
}
void UIWidget::drawText(const Rect& screenCoords)
{
g_painter.setColor(m_foregroundColor);
if(m_text.length() > 0 && m_foregroundColor.a() > 0) {
Rect textRect = screenCoords;
textRect.translate(m_textOffset);
m_font->renderText(m_text, textRect, m_textAlign, m_foregroundColor);
}
}
void UIWidget::setEnabled(bool enabled)
{
if(enabled != m_enabled) {
@@ -215,6 +274,36 @@ void UIWidget::setRect(const Rect& rect)
m_updateEventScheduled = true;
}
void UIWidget::setIcon(const std::string& iconFile)
{
m_icon = g_textures.getTexture(iconFile);
}
void UIWidget::setText(const std::string& text)
{
if(m_text != text) {
m_text = text;
// update rect size
if(!m_rect.isValid()) {
Size textSize = m_font->calculateTextRectSize(m_text);
Size newSize = getSize();
if(newSize.width() <= 0)
newSize.setWidth(textSize.width());
if(newSize.height() <= 0)
newSize.setHeight(textSize.height());
resize(newSize);
}
onTextChange(text);
}
}
void UIWidget::setFont(const std::string& fontName)
{
m_font = g_fonts.getFont(fontName);
}
void UIWidget::bindRectToParent()
{
Rect boundRect = m_rect;
@@ -672,8 +761,8 @@ void UIWidget::updateLayout()
void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
{
try {
onStyleApply(styleNode);
callLuaField("onStyleApply", styleNode);
onStyleApply(styleNode->tag(), styleNode);
callLuaField("onStyleApply", styleNode->tag(), styleNode);
} catch(Exception& e) {
logError("Failed to apply style to widget '", m_id, "' style: ", e.what());
}
@@ -862,7 +951,7 @@ void UIWidget::updateStyle()
m_stateStyle = newStateStyle;
}
void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
void UIWidget::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
// first set id
if(const OTMLNodePtr& node = styleNode->get("id"))
@@ -878,8 +967,16 @@ void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
}
else if(node->tag() == "border-image")
setImage(BorderImage::loadFromOTML(node));
if(node->tag() == "icon")
setIcon(node->value());
else if(node->tag() == "text")
setText(node->value());
else if(node->tag() == "text-align")
setTextAlign(Fw::translateAlignment(node->value()));
else if(node->tag() == "text-offset")
setTextOffset(node->value<Point>());
else if(node->tag() == "font")
setFont(g_fonts.getFont(node->value()));
setFont(node->value());
else if(node->tag() == "color")
setForegroundColor(node->value<Color>());
else if(node->tag() == "background-color")
@@ -902,7 +999,7 @@ void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
setHeight(node->value<int>());
else if(node->tag() == "fixed-size")
setSizeFixed(node->value<bool>());
else if(node->tag() == "position")
else if(node->tag() == "pos")
moveTo(node->value<Point>());
else if(node->tag() == "x")
setX(node->value<int>());
@@ -1007,7 +1104,7 @@ void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
}
// lua functions
} else if(boost::starts_with(node->tag(), "@")) {
// on load once
// load once
if(m_firstOnStyle) {
std::string funcName = node->tag().substr(1);
std::string funcOrigin = "@" + node->source() + "[" + node->tag() + "]";
@@ -1051,6 +1148,17 @@ void UIWidget::onHoverChange(bool hovered)
g_ui.getRootWidget()->updateState(Fw::HoverState);
}
void UIWidget::onTextChange(const std::string& text)
{
callLuaField("onTextChange", text);
}
void UIWidget::onFontChange(const std::string& font)
{
callLuaField("onFontChange", font);
}
bool UIWidget::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
{
if(callLuaField<bool>("onKeyPress", keyCode, keyText, keyboardModifiers))
@@ -1140,6 +1248,9 @@ bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button)
void UIWidget::onMouseRelease(const Point& mousePos, Fw::MouseButton button)
{
if(isPressed() && getRect().contains(mousePos))
callLuaField("onClick");
callLuaField("onMouseRelease", mousePos, button);
// do a backup of children list, because it may change while looping it

View File

@@ -27,6 +27,7 @@
#include <framework/luascript/luaobject.h>
#include <framework/graphics/declarations.h>
#include <framework/otml/otmlnode.h>
#include <framework/graphics/font.h>
class UIWidget : public LuaObject
{
@@ -40,9 +41,17 @@ public:
void destroy();
virtual void render();
void renderSelf();
void renderChildren();
virtual void renderSelf();
virtual void renderChildren();
protected:
void drawBackground(const Rect& screenCoords);
void drawBorder(const Rect& screenCoords);
void drawImage(const Rect& screenCoords);
void drawIcon(const Rect& screenCoords);
void drawText(const Rect& screenCoords);
public:
void setVisible(bool visible);
void setEnabled(bool enabled);
void setPressed(bool pressed) { m_pressed = pressed; updateState(Fw::PressedState); }
@@ -59,7 +68,7 @@ public:
void setWidth(int width) { resize(Size(width, getHeight())); }
void setHeight(int height) { resize(Size(getWidth(), height)); }
void setImage(const ImagePtr& image) { m_image = image; }
virtual void setFont(const FontPtr& font) { m_font = font; }
void setIcon(const std::string& iconFile);
void setOpacity(int opacity) { m_opacity = opacity; }
void setBackgroundColor(const Color& color) { m_backgroundColor = color; }
void setForegroundColor(const Color& color) { m_foregroundColor = color; }
@@ -67,11 +76,16 @@ public:
void setMarginRight(int margin) { m_marginRight = margin; updateParentLayout(); }
void setMarginBottom(int margin) { m_marginBottom = margin; updateParentLayout(); }
void setMarginLeft(int margin) { m_marginLeft = margin; updateParentLayout(); }
void setText(const std::string& text);
void setTextAlign(Fw::AlignmentFlag align) { m_textAlign = align; }
void setTextOffset(const Point& offset) { m_textOffset = offset; }
void setFont(const std::string& fontName);
void setSizeFixed(bool fixed) { m_fixedSize = fixed; updateParentLayout(); }
void setLastFocusReason(Fw::FocusReason reason) { m_lastFocusReason = reason; }
void bindRectToParent();
void resize(const Size& size) { setRect(Rect(getPosition(), size)); }
void resize(const Size& size) { setRect(Rect(getPos(), size)); }
void resizeToText() { resize(getTextSize()); }
void moveTo(const Point& pos) { setRect(Rect(pos, getSize())); }
void hide() { setVisible(false); }
void show() { setVisible(true); }
@@ -84,6 +98,7 @@ public:
void ungrabMouse();
void grabKeyboard();
void ungrabKeyboard();
void clearText() { setText(""); }
bool isActive() { return hasState(Fw::ActiveState); }
bool isEnabled() { return !hasState(Fw::DisabledState); }
@@ -111,15 +126,13 @@ public:
UILayoutPtr getLayout() { return m_layout; }
UIWidgetPtr getParent() { return m_parent.lock(); }
UIWidgetPtr getRootParent();
Point getPosition() { return m_rect.topLeft(); }
Point getPos() { return m_rect.topLeft(); }
Size getSize() { return m_rect.size(); }
Rect getRect() { return m_rect; }
int getX() { return m_rect.x(); }
int getY() { return m_rect.y(); }
int getWidth() { return m_rect.width(); }
int getHeight() { return m_rect.height(); }
ImagePtr getImage() { return m_image; }
FontPtr getFont() { return m_font; }
Color getForegroundColor() { return m_foregroundColor; }
Color getBackgroundColor() { return m_backgroundColor; }
int getOpacity() { return m_opacity; }
@@ -127,6 +140,12 @@ public:
int getMarginRight() { return m_marginRight; }
int getMarginBottom() { return m_marginBottom; }
int getMarginLeft() { return m_marginLeft; }
std::string getText() { return m_text; }
Fw::AlignmentFlag getTextAlign() { return m_textAlign; }
Point getTextOffset() { return m_textOffset; }
std::string getFont() { return m_font->getName(); }
Size getTextSize() { return m_font->calculateTextRectSize(m_text); }
Fw::FocusReason getLastFocusReason() { return m_lastFocusReason; }
OTMLNodePtr getStyle() { return m_style; }
std::string getStyleName() { return m_style->tag(); }
@@ -175,27 +194,18 @@ private:
void updateStyle();
protected:
/// Triggered when widget style is changed
virtual void onStyleApply(const OTMLNodePtr& styleNode);
/// Triggered when widget is moved or resized
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
/// Triggered when widget gets or loses focus
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
/// Triggered when the mouse enters or leaves widget area
virtual void onHoverChange(bool hovered);
/// Triggered when user presses key while widget has focus
virtual void onTextChange(const std::string& text);
virtual void onFontChange(const std::string& font);
virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
/// Triggered when user releases key while widget has focus
virtual bool onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers);
/// Triggered when a mouse button is pressed down while mouse pointer is inside widget area
virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
/// Triggered when a mouse button is released
virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);
/// Triggered when mouse moves (even when the mouse is outside widget area)
virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
/// Triggered when mouse middle button wheels inside widget area
virtual bool onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction);
friend class UIManager;
protected:
@@ -218,6 +228,7 @@ protected:
OTMLNodePtr m_style;
OTMLNodePtr m_stateStyle;
ImagePtr m_image;
TexturePtr m_icon;
FontPtr m_font;
Color m_backgroundColor;
Color m_foregroundColor;
@@ -227,6 +238,9 @@ protected:
int m_marginRight;
int m_marginBottom;
int m_marginLeft;
std::string m_text;
Point m_textOffset;
Fw::AlignmentFlag m_textAlign;
};
#endif

View File

@@ -56,9 +56,9 @@ void UIWindow::render()
m_font->renderText(m_title, headTextRect, m_titleAlign, m_foregroundColor);
}
void UIWindow::onStyleApply(const OTMLNodePtr& styleNode)
void UIWindow::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleNode);
UIWidget::onStyleApply(styleName, styleNode);
for(OTMLNodePtr node : styleNode->children()) {
if(node->tag() == "head-height")
@@ -94,7 +94,7 @@ bool UIWindow::onMousePress(const Point& mousePos, Fw::MouseButton button)
m_moving = true;
m_movingReference = mousePos - getRect().topLeft();
m_oldIndex = getParent()->getChildIndex(asUIWidget());
m_oldPos = getPosition();
m_oldPos = getPos();
getParent()->moveChildToTop(asUIWidget());
}
}

View File

@@ -41,7 +41,7 @@ public:
std::string getTitle() const { return m_title; }
protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);