Compare commits

...

19 Commits

Author SHA1 Message Date
David Capello e6401db3ed
Merge 35d209a4b1 into 1b16cfbe71 2025-10-07 14:25:24 +00:00
David Capello 35d209a4b1 Remove ASSERT() that can fail if we paste a RTL text
build-auto / build-auto (Debug, macos-latest) (push) Waiting to run Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Waiting to run Details
build-auto / build-auto (Debug, windows-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Waiting to run Details
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-10-07 11:25:00 -03:00
David Capello c781d82cf6 Match text caret size with Entry widget 2025-10-07 11:08:41 -03:00
David Capello 0dc4bc9aa7 Use gfx::RectF instead of gfx::Rect for text line bounds 2025-10-07 09:32:53 -03:00
David Capello fb4f4d9fa6 Fix TextEdit selection bounds for multiple lines
If we select from the beginning of a line to the previous line the
selection painting process was including the first character of the
line where we started, but it shouldn't be included (as the cursor
started in pos=0).
2025-10-07 09:25:38 -03:00
David Capello 0faf9c0206 Fix TextEdit::caretFromPosition() when lines have different heights 2025-10-07 08:06:47 -03:00
David Capello d8193f5acc Invalidate all blobs after changing theme
We've moved the InitTheme code from the InitTheme.connect() signal to
the onInitTheme() member function.
2025-10-07 08:06:47 -03:00
David Capello 3c0b4e2940 Implement "selection by words" after double-clicking
This is the same behavior as in ui::Entry widget.
2025-10-07 08:06:47 -03:00
David Capello c99360e4d5 Improve caret/char selection with the mouse 2025-10-07 08:06:47 -03:00
David Capello b93a2fc035 Fix caret position when a line has multiple runs (e.g. there's an emoji present) 2025-10-07 08:06:47 -03:00
David Capello 27cd52ba3b Jump between words correctly with Ctrl+Left/Right 2025-10-07 08:06:47 -03:00
David Capello f6ed430bd6 Change size_t to int for position/line numbers 2025-10-07 08:06:47 -03:00
David Capello d1f010cc47 Fix End key to go to EOL and added Ctrl+Home/End to go to BOF/EOF 2025-10-07 08:06:47 -03:00
David Capello 7e4b310a42 Enter from the numeric keypad can be used for new lines too 2025-10-07 08:06:47 -03:00
David Capello 85863cf4ed We cannot bypass onSetText() as ui::Entry requires this
Without this fix, "Run Command" will crash.
2025-10-07 08:06:47 -03:00
Christian Kaiser f3d36ca4c4 User data with multiple lines of text (new TextEdit widget) (#3130, #3131, #4743, #4968) 2025-10-07 08:06:47 -03:00
David Capello 1b16cfbe71 Merge branch 'main' into beta
build-auto / build-auto (Debug, macos-latest) (push) Waiting to run Details
build-auto / build-auto (Debug, ubuntu-latest) (push) Waiting to run Details
build-auto / build-auto (Debug, windows-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, macos-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, ubuntu-latest) (push) Waiting to run Details
build-auto / build-auto (RelWithDebInfo, windows-latest) (push) Waiting to run Details
build / build (Debug, macos-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, macos-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, lua, cli) (push) Waiting to run Details
build / build (Debug, windows-latest, noscripts, cli) (push) Waiting to run Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Waiting to run Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Waiting to run Details
2025-10-07 08:06:10 -03:00
David Capello d3ef5c61da Update laf module 2025-10-07 08:05:18 -03:00
David Capello 107e846911 Remove direct TRACEARGS() calls
build / build (Debug, macos-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, macos-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, ubuntu-latest, noscripts, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, lua, cli) (push) Has been cancelled Details
build / build (Debug, windows-latest, noscripts, cli) (push) Has been cancelled Details
build / build (RelWithDebInfo, macos-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, ubuntu-latest, lua, gui) (push) Has been cancelled Details
build / build (RelWithDebInfo, windows-latest, lua, gui) (push) Has been cancelled Details
2025-10-01 16:53:07 -03:00
23 changed files with 1395 additions and 38 deletions

View File

@ -1046,6 +1046,12 @@
<text color="slider_empty_text" align="center middle"/>
<text color="slider_empty_text" align="center middle" state="focus" y="1"/>
</style>
<style id="textedit" border="2">
<background color="textbox_face" />
<text color="textbox_text" align="left" />
<text color="selected" align="left" state="selected" />
<text color="selected_text" align="left" state="selected" />
</style>
<style id="mini_slider" extends="slider" font="mini">
<background part="mini_slider_empty"/>
<text color="slider_empty_text" align="center middle"/>

View File

@ -4,8 +4,8 @@
<gui>
<window id="layer_properties" text="@.title">
<vbox>
<grid id="properties_grid" columns="3">
<label text="@.name" for="name" />
<grid id="properties_grid" columns="3" expansive="true">
<label text="@.name" />
<entry text="" id="name" magnet="true" maxsize="256" minwidth="64" cell_align="horizontal" />
<button id="user_data" icon="icon_user_data" tooltip="@general.user_data" />

View File

@ -6,6 +6,8 @@
<label id="color_label" text="@.color" for="color" />
<label id="entry_label" text="@.user_data" for="entry" />
<colorpicker id="color" simple="true" expansive="true" />
<entry id="entry" maxsize="65535" minwidth="128" expansive="true" />
<view id="text_edit_view" height="30" expansive="true">
<textedit id="text_edit" />
</view>
</hbox>
</gui>

2
laf

@ -1 +1 @@
Subproject commit 39706c11063fb53cf4c8e865102c6f71e2606906
Subproject commit 29aa044517059df87158c9e5f26c92572effb103

View File

@ -344,7 +344,7 @@ private:
color_t c = m_cel->data()->userData().color();
m_userDataView.color()->setColor(
Color::fromRgb(rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c)));
m_userDataView.entry()->setText(m_cel->data()->userData().text());
m_userDataView.textEdit()->setText(m_cel->data()->userData().text());
// Set last filled values in CelPropertiesWindow
m_lastValues.opacity = m_cel->opacity();
m_lastValues.zIndex = m_cel->zIndex();

View File

@ -465,7 +465,7 @@ private:
color_t c = m_layer->userData().color();
m_userDataView.color()->setColor(
Color::fromRgb(rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c)));
m_userDataView.entry()->setText(m_layer->userData().text());
m_userDataView.textEdit()->setText(m_layer->userData().text());
}
else {
name()->setText(Strings::layer_properties_no_layer());

View File

@ -34,7 +34,6 @@ namespace app { namespace script {
template<>
void push_value_to_lua(lua_State* L, const std::nullptr_t&)
{
TRACEARGS("push_value_to_lua nullptr_t");
lua_pushnil(L);
}

View File

@ -1233,6 +1233,8 @@ void SkinTheme::initWidget(Widget* widget)
widget->setStyle(styles.textboxText());
break;
case kTextEditWidget: widget->setStyle(styles.textedit()); break;
case kViewWidget:
widget->setChildSpacing(0);
widget->setBgColor(colors.windowFace());
@ -1294,12 +1296,22 @@ int SkinTheme::getScrollbarSize()
return dimensions.scrollbarSize();
}
gfx::Size SkinTheme::getEntryCaretSize(Widget* widget)
gfx::Size SkinTheme::getCaretSize(Widget* widget)
{
int caretHeight;
if (widget->type() == kTextEditWidget) {
// We cannot use the height of the widget text, because it
// includes the line height of every single line in the widget.
caretHeight = widget->font()->lineHeight();
}
else {
caretHeight = widget->textHeight();
}
if (widget->font()->type() == text::FontType::FreeType)
return gfx::Size(2 * guiscale(), widget->textHeight());
return gfx::Size(2 * guiscale(), caretHeight);
else
return gfx::Size(2 * guiscale(), widget->textHeight() + 2 * guiscale());
return gfx::Size(2 * guiscale(), caretHeight + 2 * guiscale());
}
void SkinTheme::paintEntry(PaintEvent& ev)
@ -1864,7 +1876,7 @@ void SkinTheme::drawEntryCaret(ui::Graphics* g, Entry* widget, int x, int y)
{
gfx::Color color = colors.text();
int textHeight = widget->textHeight();
gfx::Size caretSize = getEntryCaretSize(widget);
gfx::Size caretSize = getCaretSize(widget);
for (int u = x; u < x + caretSize.w; ++u)
g->drawVLine(color, u, y + textHeight / 2 - caretSize.h / 2, caretSize.h);

View File

@ -80,7 +80,7 @@ public:
void initWidget(ui::Widget* widget) override;
void getWindowMask(ui::Widget* widget, gfx::Region& region) override;
int getScrollbarSize() override;
gfx::Size getEntryCaretSize(ui::Widget* widget) override;
gfx::Size getCaretSize(ui::Widget* widget) override;
void paintEntry(ui::PaintEvent& ev) override;
void paintListBox(ui::PaintEvent& ev) override;

View File

@ -90,10 +90,9 @@ SliceWindow::SliceWindow(const doc::Sprite* sprite,
entry->Change.connect([this, entry, mod] { onModifyField(entry, mod); });
}
ui::Entry* userDataEntry = m_userDataView.entry();
userDataEntry->setSuffix("*");
userDataEntry->Change.connect(
[this, userDataEntry] { onModifyField(userDataEntry, kUserData); });
ui::TextEdit* userDataEntry = m_userDataView.textEdit();
// userDataEntry->setSuffix("*");
userDataEntry->Change.connect([this, userDataEntry] { onModifyField(nullptr, kUserData); });
ColorButton* colorButton = m_userDataView.color();
colorButton->Click.connect([this] { onPossibleColorChange(); });

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2023 Igara Studio S.A.
// Copyright (C) 2019-2025 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -50,10 +50,8 @@ TaskWidget::TaskWidget(const Type type, base::task::func_t&& func)
}
else if (m_progressBar.parent()) {
float v = m_task.progress();
if (v > 0.0f) {
TRACEARGS("progressBar setValue", int(std::clamp(v * 100.0f, 0.0f, 100.0f)));
if (v > 0.0f)
m_progressBar.setValue(int(std::clamp(v * 100.0f, 0.0f, 100.0f)));
}
}
});
m_monitorTimer.start();

View File

@ -58,14 +58,14 @@ void UserDataView::configureAndSet(const doc::UserData& userData, ui::Grid* pare
parent->addChildInCell(colorLabel(), hspan1, vspan, ui::LEFT);
parent->addChildInCell(color(), hspan2, vspan, ui::HORIZONTAL);
parent->addChildInCell(entryLabel(), hspan1, vspan, ui::LEFT);
parent->addChildInCell(entry(), hspan2, vspan, ui::HORIZONTAL);
parent->addChildInCell(textEditView(), hspan2, vspan, ui::HORIZONTAL | ui::VERTICAL);
color()->Change.connect([this] { onColorChange(); });
entry()->Change.connect([this] { onEntryChange(); });
textEdit()->Change.connect([this] { onEntryChange(); });
m_isConfigured = true;
}
m_userData = userData;
color()->setColor(Color::fromImage(doc::IMAGE_RGB, userData.color()));
entry()->setText(m_userData.text());
textEdit()->setText(m_userData.text());
setVisible(isVisible());
}
@ -79,15 +79,15 @@ void UserDataView::setVisible(bool state, bool saveAsDefault)
colorLabel()->setVisible(state);
color()->setVisible(state);
entryLabel()->setVisible(state);
entry()->setVisible(state);
textEditView()->setVisible(state);
if (saveAsDefault)
m_visibility.setValue(state);
}
void UserDataView::onEntryChange()
{
if (entry()->text() != m_userData.text()) {
m_userData.setText(entry()->text());
if (textEdit()->text() != m_userData.text()) {
m_userData.setText(textEdit()->text());
if (!m_selfUpdate)
UserDataChange();
}

View File

@ -13,9 +13,9 @@
#include "doc/user_data.h"
#include "obs/signal.h"
#include "ui/base.h"
#include "ui/entry.h"
#include "ui/grid.h"
#include "ui/label.h"
#include "ui/textedit.h"
#include "user_data.xml.h"
@ -31,7 +31,8 @@ public:
const doc::UserData& userData() const { return m_userData; }
ColorButton* color() { return m_container.color(); }
ui::Entry* entry() { return m_container.entry(); }
ui::TextEdit* textEdit() { return m_container.textEdit(); }
ui::View* textEditView() { return m_container.textEditView(); }
ui::Label* colorLabel() { return m_container.colorLabel(); }
ui::Label* entryLabel() { return m_container.entryLabel(); }

View File

@ -35,6 +35,7 @@
#include "base/fs.h"
#include "base/memory.h"
#include "os/system.h"
#include "ui/textedit.h"
#include "ui/ui.h"
#include "tinyxml2.h"
@ -259,13 +260,16 @@ Widget* WidgetLoader::convertXmlElementToWidget(const XMLElement* elem,
if (elem_name == "expr" && decimals)
((ExprEntry*)widget)->setDecimals(strtol(decimals, nullptr, 10));
}
if (elem_name == "filename") {
else if (elem_name == "filename") {
const bool buttononly = bool_attr(elem, "buttononly", false);
const app::FilenameField::Type type = (buttononly ? app::FilenameField::Type::ButtonOnly :
app::FilenameField::Type::EntryAndButton);
widget = new app::FilenameField(type, "");
}
else if (elem_name == "textedit") {
widget = new TextEdit();
}
else if (elem_name == "grid") {
const char* columns = elem->Attribute("columns");
bool same_width_columns = bool_attr(elem, "same_width_columns", false);

View File

@ -102,6 +102,8 @@ static Item convert_to_item(XMLElement* elem)
return item.typeIncl("app::DropDownButton", "app/ui/drop_down_button.h");
if (name == "entry")
return item.typeIncl("ui::Entry", "ui/entry.h");
if (name == "textedit")
return item.typeIncl("ui::TextEdit", "ui/textedit.h");
if (name == "expr")
return item.typeIncl("app::ExprEntry", "app/ui/expr_entry.h");
if (name == "filename")

View File

@ -1,5 +1,5 @@
// Aseprite Steam Wrapper
// Copyright (c) 2020-2024 Igara Studio S.A.
// Copyright (c) 2020-2025 Igara Studio S.A.
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
@ -153,8 +153,6 @@ public:
CallbackMsg_t msg;
if (SteamAPI_ManualDispatch_GetNextCallback(m_pipe, &msg)) {
// TRACEARGS("SteamAPI_ManualDispatch_GetNextCallback", msg.callback);
bool disconnected = false;
switch (msg.callback) {
case kSteamServersDisconnected:

View File

@ -50,6 +50,7 @@ add_library(ui-lib
style.cpp
system.cpp
textbox.cpp
textedit.cpp
theme.cpp
timer.cpp
tooltips.cpp

View File

@ -139,7 +139,7 @@ gfx::Point Entry::caretPosOnScreen() const
void Entry::setCaretPos(const int pos)
{
gfx::Size caretSize = theme()->getEntryCaretSize(this);
gfx::Size caretSize = theme()->getCaretSize(this);
int textlen = lastCaretPos();
m_caret = std::clamp(pos, 0, textlen);
m_scroll = std::clamp(m_scroll, 0, textlen);
@ -521,7 +521,7 @@ gfx::Size Entry::sizeHintWithText(Entry* entry, const std::string& text)
{
const auto& font = entry->font();
int w = font->textLength(text) + +2 * entry->theme()->getEntryCaretSize(entry).w +
int w = font->textLength(text) + +2 * entry->theme()->getCaretSize(entry).w +
entry->border().width();
w = std::min(w, guiscale() * kMaxWidthHintForEntry);
@ -546,7 +546,7 @@ void Entry::onSizeHint(SizeHintEvent& ev)
const auto& font = this->font();
int trailing = font->textLength(getSuffix());
trailing = std::max(trailing, 2 * theme()->getEntryCaretSize(this).w);
trailing = std::max(trailing, 2 * theme()->getCaretSize(this).w);
int w = font->textLength("w") * std::min(m_maxsize, 6) + +trailing + border().width();
@ -1012,7 +1012,7 @@ void Entry::recalcCharBoxes(const std::string& text)
box.codepoint = 0;
box.from = box.to = lastTextIndex;
box.x = lastX;
box.width = theme()->getEntryCaretSize(this).w;
box.width = theme()->getCaretSize(this).w;
m_boxes.push_back(box);
}

View File

@ -141,7 +141,7 @@ void IntEntry::onSizeHint(SizeHintEvent& ev)
{
const text::FontRef& font = this->font();
int trailing = font->textLength(getSuffix());
trailing = std::max(trailing, 2 * theme()->getEntryCaretSize(this).w);
trailing = std::max(trailing, 2 * theme()->getCaretSize(this).w);
int min_w = font->textLength(m_slider->convertValueToText(m_min));
int max_w = font->textLength(m_slider->convertValueToText(m_max)) + trailing;

1125
src/ui/textedit.cpp Normal file

File diff suppressed because it is too large Load Diff

208
src/ui/textedit.h Normal file
View File

@ -0,0 +1,208 @@
// Aseprite
// Copyright (C) 2024-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifndef UI_TEXT_EDIT_H_INCLUDED
#define UI_TEXT_EDIT_H_INCLUDED
#pragma once
#include "text/font_mgr.h"
#include "text/text_blob.h"
#include "ui/box.h"
#include "ui/theme.h"
#include "ui/view.h"
#include <algorithm>
namespace ui {
using namespace text;
class TextEdit : public Widget,
public ViewableWidget {
public:
TextEdit();
void cut();
void copy();
void paste();
void selectAll();
obs::signal<void()> Change;
protected:
bool onProcessMessage(Message* msg) override;
void onPaint(PaintEvent& ev) override;
void onInitTheme(InitThemeEvent& ev) override;
void onSizeHint(SizeHintEvent& ev) override;
void onScrollRegion(ScrollRegionEvent& ev) override;
void onSetText() override;
void onSetFont() override;
bool onKeyDown(const KeyMessage* keyMessage);
bool onMouseMove(const MouseMessage* mouseMessage);
private:
struct Line {
std::string text;
std::vector<TextBlob::Utf8Range> utfSize;
int glyphCount = 0;
text::TextBlobRef blob;
int width = 0;
int height = 0;
// Line index for more convenient loops
int i = 0;
void buildBlob(const Widget* forWidget);
// Insert text into this line based on a caret position, taking into account utf8 size.
void insertText(int pos, const std::string& str);
gfx::RectF getBounds(int glyph) const;
// Get the screen size between the start and end glyph positions.
gfx::RectF getBounds(int startGlyph, int endGlyph) const;
};
struct Caret {
explicit Caret(std::vector<Line>* lines = nullptr) : m_lines(lines) {}
explicit Caret(std::vector<Line>* lines, int line, int pos)
: m_line(line)
, m_pos(pos)
, m_lines(lines)
{
}
Caret(const Caret& caret) : m_line(caret.m_line), m_pos(caret.m_pos), m_lines(caret.m_lines) {}
int line() const { return m_line; }
int pos() const { return m_pos; }
void setPos(int pos);
void setLine(int line) { m_line = line; }
void set(int line, int pos);
bool left(bool byWord = false);
// Moves the position to the next word on the left, doesn't wrap around lines.
bool leftWord();
bool right(bool byWord = false);
// Moves the position to the next word on the right, doesn't wrap around lines.
bool rightWord();
void up();
void down();
bool isLastInLine() const { return m_pos == lineObj().glyphCount; }
bool isLastLine() const { return m_line == m_lines->size() - 1; }
// Go to the end of line.
void eol();
// Returns the absolute position of the caret, aka the position in the main string that has all
// the newlines.
int absolutePos() const;
bool isWordPart() const;
void advanceBy(int characters);
bool isValid() const;
void clear();
bool operator==(const Caret& other) const
{
return m_line == other.m_line && m_pos == other.m_pos;
}
bool operator!=(const Caret& other) const
{
return m_line != other.m_line || m_pos != other.m_pos;
}
bool operator<(const Caret& other) const
{
if (m_line < other.m_line)
return true;
if (m_line > other.m_line)
return false;
return m_pos < other.m_pos;
}
private:
int m_line = 0;
int m_pos = 0;
std::string_view text() const { return (*m_lines)[m_line].text; }
Line& lineObj() const { return (*m_lines)[m_line]; }
std::vector<Line>* m_lines;
};
struct Selection {
Selection() = default;
Selection(const Caret& startCaret, const Caret& endCaret) { set(startCaret, endCaret); }
static Selection SelectWords(const Caret& from);
bool isEmpty() const
{
return (m_start.line() == m_end.line() && m_start.pos() == m_end.pos());
}
void setStart(const Caret& caret) { m_start = caret; }
void setEnd(const Caret& caret) { m_end = caret; }
void set(const Caret& startCaret, const Caret& endCaret);
const Caret& start() const { return m_start; }
const Caret& end() const { return m_end; }
bool isValid() const { return m_start.isValid() && m_end.isValid(); }
void clear();
Selection& operator|=(const Selection& other)
{
m_start = std::min(m_start, other.start());
m_end = std::max(m_end, other.end());
return *this;
}
private:
Caret m_start;
Caret m_end;
};
// Get the selection rect for the given line, if any
gfx::RectF getSelectionRect(const Line& line, const gfx::PointF& offset) const;
Caret caretFromPosition(const gfx::Point& position);
void showEditPopupMenu(const gfx::Point& position);
void insertCharacter(base::codepoint_t character);
void deleteSelection();
void ensureCaretVisible();
int maxHeight() const;
void startTimer();
void stopTimer();
Selection m_selection;
Selection m_selectionWords;
Caret m_caret;
Caret m_lockedSelectionStart;
std::vector<Line> m_lines;
// Whether or not we're currently drawing the caret, driven by a timer.
bool m_drawCaret = false;
// The last position the caret was drawn, to invalidate that region when repainting.
gfx::Rect m_caretRect;
// The total size of the complete text, calculated as the longest single line width and the sum of
// the total line heights
gfx::Size m_textSize;
// Color cache
gfx::Color m_colorBG;
gfx::Color m_colorSelected;
os::Paint m_textPaint;
os::Paint m_selectedTextPaint;
};
} // namespace ui
#endif

View File

@ -74,9 +74,10 @@ public:
virtual void getWindowMask(Widget* widget, gfx::Region& region) {}
virtual void setDecorativeWidgetBounds(Widget* widget);
virtual int getScrollbarSize() { return kDefaultFontHeight; }
virtual gfx::Size getEntryCaretSize(Widget* widget) { return gfx::Size(kDefaultFontHeight, 1); }
virtual gfx::Size getCaretSize(Widget* widget) { return gfx::Size(kDefaultFontHeight, 1); }
virtual void paintEntry(PaintEvent& ev) {}
virtual void paintTextEdit(PaintEvent& ev) {}
virtual void paintListBox(PaintEvent& ev);
virtual void paintMenu(PaintEvent& ev) {}
virtual void paintMenuItem(PaintEvent& ev) {}

View File

@ -38,6 +38,7 @@ enum WidgetType : int {
kSliderWidget,
kSplitterWidget,
kTextBoxWidget,
kTextEditWidget,
kViewScrollbarWidget,
kViewViewportWidget,
kViewWidget,