// ================================================================================ // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås == // == See tb_core.h for more information. == // ================================================================================ #include "tb_core.h" #include "tb_widgets_reader.h" #include "tb_window.h" #include "tb_editfield.h" #include "tb_font_renderer.h" #include "tb_tempbuffer.h" #include namespace tb { #ifdef TB_RUNTIME_DEBUG_INFO TBDebugInfo g_tb_debug; TBDebugInfo::TBDebugInfo() { memset(settings, 0, sizeof(int) * NUM_SETTINGS); } /** Window showing runtime debug settings. */ class DebugSettingsWindow : public TBWindow, public TBWidgetListener { public: TBEditField *output; TBOBJECT_SUBCLASS(DebugSettingsWindow, TBWindow); DebugSettingsWindow(TBWidget *root) { SetText("Debug settings"); g_widgets_reader->LoadData(this, "TBLayout: axis: y, distribution: available, position: left\n" " TBLayout: id: 'container', axis: y, size: available\n" " TBTextField: text: 'Event output:'\n" " TBEditField: id: 'output', gravity: all, multiline: 1, wrap: 0\n" " lp: pref-height: 100dp"); AddCheckbox(TBDebugInfo::LAYOUT_BOUNDS, "Layout bounds"); AddCheckbox(TBDebugInfo::LAYOUT_CLIPPING, "Layout clipping"); AddCheckbox(TBDebugInfo::LAYOUT_PS_DEBUGGING, "Layout size calculation"); AddCheckbox(TBDebugInfo::RENDER_BATCHES, "Render batches"); AddCheckbox(TBDebugInfo::RENDER_SKIN_BITMAP_FRAGMENTS, "Render skin bitmap fragments"); AddCheckbox(TBDebugInfo::RENDER_FONT_BITMAP_FRAGMENTS, "Render font bitmap fragments"); output = GetWidgetByIDAndType(TBIDC("output")); TBRect bounds(0, 0, root->GetRect().w, root->GetRect().h); SetRect(GetResizeToFitContentRect().CenterIn(bounds).MoveIn(bounds).Clip(bounds)); root->AddChild(this); TBWidgetListener::AddGlobalListener(this); } ~DebugSettingsWindow() { TBWidgetListener::RemoveGlobalListener(this); } void AddCheckbox(TBDebugInfo::SETTING setting, const char *str) { TBCheckBox *check = new TBCheckBox(); check->SetValue(g_tb_debug.settings[setting]); check->data.SetInt(setting); check->SetID(TBIDC("check")); TBClickLabel *label = new TBClickLabel(); label->SetText(str); label->GetContentRoot()->AddChild(check, WIDGET_Z_BOTTOM); GetWidgetByID(TBIDC("container"))->AddChild(label); } virtual bool OnEvent(const TBWidgetEvent &ev) { if (ev.type == EVENT_TYPE_CLICK && ev.target->GetID() == TBIDC("check")) { // Update setting and invalidate g_tb_debug.settings[ev.target->data.GetInt()] = ev.target->GetValue(); GetParentRoot()->Invalidate(); return true; } return TBWindow::OnEvent(ev); } virtual void OnPaint(const PaintProps &paint_props) { // Draw stuff to the right of the debug window g_renderer->Translate(GetRect().w, 0); // Draw skin bitmap fragments if (TB_DEBUG_SETTING(RENDER_SKIN_BITMAP_FRAGMENTS)) g_tb_skin->Debug(); // Draw font glyph fragments (the font of the hovered widget) if (TB_DEBUG_SETTING(RENDER_FONT_BITMAP_FRAGMENTS)) { TBWidget *widget = TBWidget::hovered_widget ? TBWidget::hovered_widget : TBWidget::focused_widget; g_font_manager->GetFontFace(widget ? widget->GetCalculatedFontDescription() : g_font_manager->GetDefaultFontDescription())->Debug(); } g_renderer->Translate(-GetRect().w, 0); } TBStr GetIDString(const TBID &id) { TBStr str; #ifdef TB_RUNTIME_DEBUG_INFO str.Append("\""); str.Append(id.debug_string); str.Append("\""); #else str.SetFormatted("%u", (uint32)id); #endif return str; } // TBWidgetListener virtual bool OnWidgetInvokeEvent(TBWidget *widget, const TBWidgetEvent &ev) { // Skip these events for now if (ev.IsPointerEvent()) return false; // Always ignore activity in this window (or we might get endless recursion) if (TBWindow *window = widget->GetParentWindow()) if (TBSafeCast(window)) return false; TBTempBuffer buf; buf.AppendString(GetEventTypeStr(ev.type)); buf.AppendString(" ("); buf.AppendString(widget->GetClassName()); buf.AppendString(")"); buf.AppendString(" id: "); buf.AppendString(GetIDString(ev.target->GetID())); if (ev.ref_id) { buf.AppendString(", ref_id: "); buf.AppendString(GetIDString(ev.ref_id)); } if (ev.type == EVENT_TYPE_CHANGED) { TBStr extra, text; if (ev.target->GetText(text) && text.Length() > 24) sprintf(text.CStr() + 20, "..."); extra.SetFormatted(", value: %.2f (\"%s\")", ev.target->GetValueDouble(), text.CStr()); buf.AppendString(extra); } buf.AppendString("\n"); // Append the line to the output textfield TBStyleEdit *se = output->GetStyleEdit(); se->selection.SelectNothing(); se->AppendText(buf.GetData(), TB_ALL_TO_TERMINATION, true); se->ScrollIfNeeded(false, true); // Remove lines from the top if we exceed the height limit. const int height_limit = 2000; int current_height = se->GetContentHeight(); if (current_height > height_limit) { se->caret.Place(TBPoint(0, current_height - height_limit)); se->selection.SelectToCaret(se->blocks.GetFirst(), 0); se->Delete(); } return false; } const char *GetEventTypeStr(EVENT_TYPE type) const { switch (type) { case EVENT_TYPE_CLICK: return "CLICK"; case EVENT_TYPE_LONG_CLICK: return "LONG_CLICK"; case EVENT_TYPE_POINTER_DOWN: return "POINTER_DOWN"; case EVENT_TYPE_POINTER_UP: return "POINTER_UP"; case EVENT_TYPE_POINTER_MOVE: return "POINTER_MOVE"; case EVENT_TYPE_RIGHT_POINTER_UP: return "RIGHT_POINTER_UP"; case EVENT_TYPE_RIGHT_POINTER_DOWN: return "RIGHT_POINTER_DOWN"; case EVENT_TYPE_TOUCH_DOWN: return "TOUCH_DOWN"; case EVENT_TYPE_TOUCH_UP: return "TOUCH_UP"; case EVENT_TYPE_TOUCH_MOVE: return "TOUCH_MOVE"; case EVENT_TYPE_TOUCH_CANCEL: return "TOUCH_CANCEL"; case EVENT_TYPE_WHEEL: return "WHEEL"; case EVENT_TYPE_CHANGED: return "CHANGED"; case EVENT_TYPE_KEY_DOWN: return "KEY_DOWN"; case EVENT_TYPE_KEY_UP: return "KEY_UP"; case EVENT_TYPE_SHORTCUT: return "SHORT_CUT"; case EVENT_TYPE_CONTEXT_MENU: return "CONTEXT_MENU"; default: return "[UNKNOWN]"; }; } }; void ShowDebugInfoSettingsWindow(TBWidget *root) { new DebugSettingsWindow(root); } #endif // TB_RUNTIME_DEBUG_INFO }; // namespace tb