Add ListView, make FrameLayout do something

This commit is contained in:
Henrik Rydgard committed 2013-06-09 11:20:15 +02:00
1 parent 2143b5b608
commit bc2a18eeee
8 files changed
+120 -24

No files matched your search

+9 -3
View File
@@ -95,8 +95,7 @@ void ScreenManager::sendMessage(const char *msg, const char *value) {
stack_.back().screen->sendMessage(msg, value);
}
void ScreenManager::deviceLost()
{
void ScreenManager::deviceLost() {
if (!stack_.empty())
stack_.back().screen->deviceLost();
// Dialogs too? Nah, they should only use the standard UI texture anyway.
@@ -124,6 +123,9 @@ void ScreenManager::push(Screen *screen, int layerFlags) {
switchToNext();
}
screen->setScreenManager(this);
if (screen->isTransparent()) {
layerFlags |= LAYER_TRANSPARENT;
}
Layer layer = {screen, layerFlags};
stack_.push_back(layer);
}
@@ -157,7 +159,11 @@ void ScreenManager::processFinishDialog() {
}
Screen *caller = topScreen();
caller->dialogFinished(dialogFinished_, dialogResult_);
if (caller) {
caller->dialogFinished(dialogFinished_, dialogResult_);
} else {
ELOG("ERROR: no top screen when finishing dialog");
}
delete dialogFinished_;
dialogFinished_ = 0;
}
+2
View File
@@ -51,6 +51,8 @@ public:
virtual void *dialogData() { return 0; }
virtual bool isTransparent() { return false; }
private:
ScreenManager *screenManager_;
DISALLOW_COPY_AND_ASSIGN(Screen);
+1 -1
View File
@@ -24,7 +24,7 @@ void UIScreen::render() {
UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_);
screenManager()->getUIContext()->Begin();
DrawBackground();
DrawBackground(*screenManager()->getUIContext());
root_->Draw(*screenManager()->getUIContext());
screenManager()->getUIContext()->End();
screenManager()->getUIContext()->Flush();
+1 -1
View File
@@ -17,7 +17,7 @@ public:
protected:
virtual void CreateViews() = 0;
virtual void DrawBackground() {}
virtual void DrawBackground(UIContext &dc) {}
void RecreateViews() { recreateViews_ = true; }
+12 -1
View File
@@ -154,8 +154,19 @@ Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) {
layoutParams_->height = ITEM_HEIGHT;
}
void Item::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
w = 0.0f;
h = 0.0f;
}
void ClickableItem::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
w = 0.0f;
h = 0.0f;
}
ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) {
layoutParams_->width = FILL_PARENT;
if (layoutParams_->width == WRAP_CONTENT)
layoutParams_->width = FILL_PARENT;
layoutParams_->height = ITEM_HEIGHT;
}
+5 -9
View File
@@ -183,14 +183,16 @@ public:
// Call this from UI thread
void Update();
// This is suggested for use in most cases. Autobinds, allowing for neat syntax.
template<class T>
void Handle(T *thiz, EventReturn (T::* theCallback)(EventParams &e)) {
Add(std::bind(theCallback, thiz, placeholder::_1));
}
private:
// Sometimes you have an already-bound function<>, just use this then.
void Add(std::function<EventReturn(EventParams&)> func);
private:
recursive_mutex mutex_;
std::vector<HandlerRegistration> handlers_;
bool triggered_;
@@ -381,19 +383,13 @@ private:
class Item : public InertView {
public:
Item(LayoutParams *layoutParams);
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const {
w = 0.0f;
h = 0.0f;
}
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
};
class ClickableItem : public Clickable {
public:
ClickableItem(LayoutParams *layoutParams);
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const {
w = 0.0f;
h = 0.0f;
}
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
// Draws the item background.
virtual void Draw(UIContext &dc);
+52 -8
View File
@@ -1,4 +1,5 @@
#include "base/display.h"
#include "base/functional.h"
#include "base/logging.h"
#include "ui/ui_context.h"
#include "ui/view.h"
@@ -368,7 +369,18 @@ void FrameLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ve
}
void FrameLayout::Layout() {
for (size_t i = 0; i < views_.size(); i++) {
float w = views_[i]->GetMeasuredWidth();
float h = views_[i]->GetMeasuredHeight();
Bounds bounds;
bounds.w = w;
bounds.h = h;
bounds.x = bounds_.x + (measuredWidth_ - w) / 2;
bounds.y = bounds_.y + (measuredWidth_ - h) / 2;
views_[i]->SetBounds(bounds);
}
}
void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) {
@@ -537,8 +549,8 @@ void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v
if (params->top >= 0 && params->bottom >= 0) {
height = measuredHeight_ - params->top - params->bottom;
}
specW = MeasureSpec(EXACTLY, width);
specH = MeasureSpec(EXACTLY, height);
specW = width < 0 ? MeasureSpec(UNSPECIFIED) : MeasureSpec(EXACTLY, width);
specH = height < 0 ? MeasureSpec(UNSPECIFIED) : MeasureSpec(EXACTLY, height);
}
views_[i]->Measure(dc, specW, specH);
@@ -562,12 +574,18 @@ void AnchorLayout::Layout() {
bottom = params->bottom;
}
if (left >= 0) vBounds.x = bounds_.x + left;
if (top >= 0) vBounds.y = bounds_.y + top;
if (right >= 0) vBounds.x = bounds_.x2() - right - vBounds.w;
if (bottom >= 0) vBounds.y = bounds_.y2() - bottom - vBounds.y;
if (left >= 0)
vBounds.x = bounds_.x + left;
else if (right >= 0)
vBounds.x = bounds_.x2() - right - vBounds.w;
if (top >= 0)
vBounds.y = bounds_.y + top;
else if (bottom >= 0)
vBounds.y = bounds_.y2() - bottom - vBounds.h;
views_[i]->SetBounds(vBounds);
views_[i]->Layout();
}
}
@@ -628,8 +646,7 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) {
}
void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) {
if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN))
{
if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) {
EnableFocusMovement(true);
if (!GetFocusedView()) {
root->SetFocus();
@@ -651,4 +668,31 @@ void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) {
root->Update(input_state);
}
ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams)
: ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) {
// Let's not be clever yet, we'll just create them all up front and add them all in.
for (int i = 0; i < adaptor_->GetNumItems(); i++) {
View * v = Add(adaptor_->CreateItemView(i));
adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, placeholder::_1));
}
}
EventReturn ListView::OnItemCallback(int num, EventParams &e) {
EventParams ev;
ev.v = e.v;
ev.a = num;
OnChoice.Trigger(ev);
return EVENT_DONE;
}
View *ChoiceListAdaptor::CreateItemView(int index) {
return new Choice(items_[index]);
}
bool ChoiceListAdaptor::AddEventCallback(View *view, std::function<EventReturn(EventParams&)> callback) {
Choice *choice = (Choice *)view;
choice->OnClick.Add(callback);
return EVENT_DONE;
}
} // namespace UI
+38 -1
View File
@@ -51,6 +51,7 @@ protected:
};
// A frame layout contains a single child view (normally).
// It simply centers the child view.
class FrameLayout : public ViewGroup {
public:
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
@@ -65,7 +66,9 @@ enum {
class AnchorLayoutParams : public LayoutParams {
public:
AnchorLayoutParams(Size w, Size h, float l, float t, float r, float b)
: LayoutParams(w, h), left(l), top(t), right(r), bottom(b) {}
: LayoutParams(w, h), left(l), top(t), right(r), bottom(b) {
}
AnchorLayoutParams(float l, float t, float r, float b)
: LayoutParams(WRAP_CONTENT, WRAP_CONTENT), left(l), top(t), right(r), bottom(b) {}
@@ -232,6 +235,40 @@ private:
std::vector<View *> tabs_;
};
// Yes, this feels a bit Java-ish...
class ListAdaptor {
public:
virtual ~ListAdaptor() {}
virtual View *CreateItemView(int index) = 0;
virtual int GetNumItems() = 0;
virtual bool AddEventCallback(View *view, std::function<EventReturn(EventParams&)> callback) { return false; }
};
class ChoiceListAdaptor {
public:
ChoiceListAdaptor(const char *items[], int numItems) : items_(items), numItems_(numItems) {}
virtual View *CreateItemView(int index);
virtual int GetNumItems() { return numItems_; }
virtual bool AddEventCallback(View *view, std::function<EventReturn(EventParams&)> callback);
private:
const char **items_;
int numItems_;
};
// A list view is a scroll view with autogenerated items.
// In the future, it might be smart and load/unload items as they go, but currently not.
class ListView : public ScrollView {
public:
ListView(ListAdaptor *a, LayoutParams *layoutParams);
Event OnChoice;
private:
EventReturn OnItemCallback(int num, EventParams &e);
ListAdaptor *adaptor_;
};
void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root);
void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root);