// ================================================================================ // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås == // == See tb_core.h for more information. == // ================================================================================ #include "tb_widget_value.h" #include "tb_widgets.h" namespace tb { // == TBWidgetValueConnection =========================================================== void TBWidgetValueConnection::Connect(TBWidgetValue *value, TBWidget *widget) { Unconnect(); m_widget = widget; m_value = value; m_value->m_connections.AddLast(this); m_value->SyncToWidget(m_widget); } void TBWidgetValueConnection::Unconnect() { if (m_value) m_value->m_connections.Remove(this); m_value = nullptr; m_widget = nullptr; } void TBWidgetValueConnection::SyncFromWidget(TBWidget *source_widget) { if (m_value) m_value->SetFromWidget(source_widget); } // == TBWidgetValue ===================================================================== TBWidgetValue::TBWidgetValue(const TBID &name, TBValue::TYPE type) : m_name(name) , m_value(type) , m_syncing(false) { } TBWidgetValue::~TBWidgetValue() { while (m_connections.GetFirst()) m_connections.GetFirst()->Unconnect(); } void TBWidgetValue::SetFromWidget(TBWidget *source_widget) { if (m_syncing) return; // We ended up here because syncing is in progress. // Get the value in the format TBStr text; switch (m_value.GetType()) { case TBValue::TYPE_STRING: if (!source_widget->GetText(text)) return; m_value.SetString(text, TBValue::SET_NEW_COPY); break; case TBValue::TYPE_NULL: case TBValue::TYPE_INT: m_value.SetInt(source_widget->GetValue()); break; case TBValue::TYPE_FLOAT: // FIX: TBValue should use double instead of float? m_value.SetFloat((float)source_widget->GetValueDouble()); break; default: assert(!"Unsupported value type!"); } SyncToWidgets(source_widget); } bool TBWidgetValue::SyncToWidgets(TBWidget *exclude_widget) { // FIX: Assign group to each value. Currently we only have one global group. g_value_group.InvokeOnValueChanged(this); bool fail = false; TBLinkListOf::Iterator iter = m_connections.IterateForward(); while (TBWidgetValueConnection *connection = iter.GetAndStep()) { if (connection->m_widget != exclude_widget) fail |= !SyncToWidget(connection->m_widget); } return !fail; } bool TBWidgetValue::SyncToWidget(TBWidget *dst_widget) { if (m_syncing) return true; // We ended up here because syncing is in progress. m_syncing = true; bool ret = true; switch (m_value.GetType()) { case TBValue::TYPE_STRING: ret = dst_widget->SetText(m_value.GetString()); break; case TBValue::TYPE_NULL: case TBValue::TYPE_INT: dst_widget->SetValue(m_value.GetInt()); break; case TBValue::TYPE_FLOAT: // FIX: TBValue should use double instead of float? dst_widget->SetValueDouble(m_value.GetFloat()); break; default: assert(!"Unsupported value type!"); } m_syncing = false; return ret; } void TBWidgetValue::SetInt(int value) { m_value.SetInt(value); SyncToWidgets(nullptr); } bool TBWidgetValue::SetText(const char *text) { m_value.SetString(text, TBValue::SET_NEW_COPY); return SyncToWidgets(nullptr); } void TBWidgetValue::SetDouble(double value) { // FIX: TBValue should use double instead of float? m_value.SetFloat((float)value); SyncToWidgets(nullptr); } // == TBValueGroup ================================================================================ /*extern*/ TBValueGroup g_value_group; TBWidgetValue *TBValueGroup::CreateValueIfNeeded(const TBID &name, TBValue::TYPE type) { if (TBWidgetValue *val = GetValue(name)) return val; if (TBWidgetValue *val = new TBWidgetValue(name, type)) { if (m_values.Add(name, val)) return val; else delete val; } return nullptr; } void TBValueGroup::InvokeOnValueChanged(const TBWidgetValue *value) { TBLinkListOf::Iterator iter = m_listeners.IterateForward(); while (TBValueGroupListener *listener = iter.GetAndStep()) listener->OnValueChanged(this, value); } }; // namespace tb