More work on focus.

ListBox now renders differently depending on focus state.
This commit is contained in:
Andreas Kling 2018-10-13 20:59:25 +02:00
parent 1929cb6b71
commit 6f1b384cde
Notes: sideshowbarker 2024-07-19 18:48:53 +09:00
6 changed files with 39 additions and 9 deletions

View file

@ -1,6 +1,7 @@
#include "ListBox.h"
#include "Painter.h"
#include "Font.h"
#include "Window.h"
ListBox::ListBox(Widget* parent)
: Widget(parent)
@ -19,16 +20,24 @@ unsigned ListBox::itemHeight() const
void ListBox::onPaint(PaintEvent&)
{
Painter painter(*this);
// FIXME: Reduce overdraw.
painter.fillRect(rect(), Color::White);
painter.drawRect(rect(), Color::Black);
if (isFocused())
painter.drawFocusRect(rect());
for (unsigned i = m_scrollOffset; i < m_items.size(); ++i) {
Rect itemRect(1, 1 + (i * itemHeight()), width() - 2, itemHeight());
Rect itemRect(2, 2 + (i * itemHeight()), width() - 4, itemHeight());
Rect textRect(itemRect.x() + 1, itemRect.y() + 1, itemRect.width() - 2, itemRect.height() - 2);
Color itemTextColor = foregroundColor();
if (m_selectedIndex == i) {
painter.fillRect(itemRect, Color(0, 32, 128));
if (isFocused())
painter.fillRect(itemRect, Color(0, 32, 128));
else
painter.fillRect(itemRect, Color(96, 96, 96));
itemTextColor = Color::White;
}
painter.drawText(textRect, m_items[i], Painter::TextAlignment::TopLeft, itemTextColor);

View file

@ -201,3 +201,12 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color)
}
}
}
void Painter::drawFocusRect(const Rect& rect)
{
Rect focusRect = rect;
focusRect.moveBy(1, 1);
focusRect.setWidth(focusRect.width() - 2);
focusRect.setHeight(focusRect.height() - 2);
drawRect(focusRect, Color(96, 96, 192));
}

View file

@ -22,6 +22,8 @@ public:
void drawPixel(const Point&, Color);
void drawLine(const Point& p1, const Point& p2, Color);
void drawFocusRect(const Rect&);
void xorRect(const Rect&, Color);
const Font& font() const;

View file

@ -49,6 +49,10 @@ void Widget::event(Event& event)
case Event::MouseMove:
return onMouseMove(static_cast<MouseEvent&>(event));
case Event::MouseDown:
if (auto* win = window()) {
// FIXME: if (acceptsFocus())
win->setFocusedWidget(this);
}
return onMouseDown(static_cast<MouseEvent&>(event));
case Event::MouseUp:
return onMouseUp(static_cast<MouseEvent&>(event));
@ -123,13 +127,15 @@ void Widget::setWindow(Window* window)
bool Widget::isFocused() const
{
return m_window && m_window->focusedWidget() == this;
if (auto* win = window())
return win->isActive() && win->focusedWidget() == this;
return false;
}
void Widget::setFocus(bool focus)
{
if (focus == isFocused())
return;
if (m_window)
m_window->setFocusedWidget(this);
if (auto* win = window())
win->setFocusedWidget(this);
}

View file

@ -56,8 +56,7 @@ void Window::event(Event& event)
//printf("hit test for %d,%d found: %s{%p} %d,%d\n", me.x(), me.y(), result.widget->className(), result.widget, result.localX, result.localY);
// FIXME: Re-use the existing event instead of crafting a new one?
auto localEvent = make<MouseEvent>(event.type(), result.localX, result.localY, me.button());
result.widget->event(*localEvent);
return m_mainWidget->event(event);
return result.widget->event(*localEvent);
}
return Object::event(event);
}
@ -101,10 +100,14 @@ void Window::setFocusedWidget(Widget* widget)
{
if (m_focusedWidget.ptr() == widget)
return;
auto* previouslyFocusedWidget = m_focusedWidget.ptr();
if (!widget) {
m_focusedWidget = nullptr;
return;
} else {
m_focusedWidget = widget->makeWeakPtr();
m_focusedWidget->repaint(Rect());
}
m_focusedWidget = widget->makeWeakPtr();
if (previouslyFocusedWidget)
previouslyFocusedWidget->repaint(Rect());
}

View file

@ -41,6 +41,7 @@ public:
bool isActive() const;
Widget* focusedWidget() { return m_focusedWidget.ptr(); }
const Widget* focusedWidget() const { return m_focusedWidget.ptr(); }
void setFocusedWidget(Widget*);
private: