[dasher: 40/43] GtkGameDisplay using dasher_editor_internal's GtkTextBuffer



commit 3aa7ffcb6921d278f52c4f41266833c7e4d4a3cd
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Mon Jun 20 16:10:53 2011 +0100

    GtkGameDisplay using dasher_editor_internal's GtkTextBuffer
    
    green/strikethrough-red/black text for entered/wrong/target

 Src/Gtk2/DasherControl.cpp          |   92 ++++++++++++++++++++++++++++++++++-
 Src/Gtk2/DasherControl.h            |    1 +
 Src/Gtk2/GtkDasherControl.cpp       |   12 ++---
 Src/Gtk2/GtkDasherControl.h         |    2 +-
 Src/Gtk2/dasher_editor.cpp          |    6 ++
 Src/Gtk2/dasher_editor.h            |    4 ++
 Src/Gtk2/dasher_editor_internal.cpp |   17 +++---
 7 files changed, 116 insertions(+), 18 deletions(-)
---
diff --git a/Src/Gtk2/DasherControl.cpp b/Src/Gtk2/DasherControl.cpp
index bbba009..3d950e6 100644
--- a/Src/Gtk2/DasherControl.cpp
+++ b/Src/Gtk2/DasherControl.cpp
@@ -10,6 +10,8 @@
 #include "../DasherCore/Event.h"
 #include "../DasherCore/ModuleManager.h"
 #include "dasher_main.h"
+#include "../DasherCore/GameModule.h"
+
 #include <fcntl.h>
 
 #include <gtk/gtk.h>
@@ -333,12 +335,14 @@ void CDasherControl::HandleEvent(int iParameter) {
 }
 
 void CDasherControl::editOutput(const std::string &strText, CDasherNode *pNode) {
-  g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_edit_insert", strText.c_str(), pNode->offset());
+  if (!GetBoolParameter(BP_GAME_MODE)) //GameModule sets editbox directly
+    g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_edit_insert", strText.c_str(), pNode->offset());
   CDasherInterfaceBase::editOutput(strText, pNode);
 }
 
 void CDasherControl::editDelete(const std::string &strText, CDasherNode *pNode) {
-  g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_edit_delete", strText.c_str(), pNode->offset());
+  if (!GetBoolParameter(BP_GAME_MODE)) //GameModule sets editbox directly
+    g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_edit_delete", strText.c_str(), pNode->offset());
   CDasherInterfaceBase::editDelete(strText, pNode);
 }
 
@@ -382,6 +386,90 @@ unsigned int CDasherControl::ctrlDelete(bool bForwards, CControlManager::EditDis
   return gtk_dasher_control_ctrl_delete(m_pDasherControl,bForwards,dist);
 }
 
+class GtkGameModule : public CGameModule {
+public:
+  GtkGameModule(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CDasherView *pView, CDasherModel *pModel, GtkTextBuffer *pBuffer)
+  : CGameModule(pCreator, pInterface, pView, pModel), m_pBuffer(pBuffer) {
+    m_tEntered = gtk_text_buffer_create_tag(m_pBuffer, "entered", "foreground", "#00FF00", NULL);
+    m_tWrong = gtk_text_buffer_create_tag(m_pBuffer, "wrong", "foreground", "#FF0000", "strikethrough", TRUE, NULL);
+    GtkTextIter start,end;
+    gtk_text_buffer_get_start_iter(m_pBuffer, &start);
+    m_mEntered = gtk_text_buffer_create_mark(m_pBuffer, NULL, &start, true);
+    gtk_text_buffer_get_end_iter(m_pBuffer, &end);
+    m_mTarget = gtk_text_buffer_create_mark(m_pBuffer, NULL, &end, false);
+    gtk_text_buffer_delete(m_pBuffer, &start, &end);
+  }
+
+  ~GtkGameModule() {
+    GtkTextTagTable *table = gtk_text_buffer_get_tag_table(m_pBuffer);
+    gtk_text_tag_table_remove(table, m_tEntered);
+    gtk_text_tag_table_remove(table, m_tWrong);
+
+    gtk_text_buffer_delete_mark(m_pBuffer,m_mEntered);
+    gtk_text_buffer_delete_mark(m_pBuffer,m_mTarget);
+  }
+
+  void ChunkGenerated() {
+    string sText;
+    for (vector<symbol>::const_iterator it=targetSyms().begin(); it!=targetSyms().end(); it++)
+      sText += m_pAlph->GetText(*it);
+    gtk_text_buffer_set_text(m_pBuffer, sText.c_str(), -1); //-1 for length = null-terminated
+    GtkTextIter start,end;
+    gtk_text_buffer_get_start_iter(m_pBuffer, &start);
+    gtk_text_buffer_move_mark(m_pBuffer, m_mEntered, &start);
+    gtk_text_buffer_move_mark(m_pBuffer, m_mTarget, &start);
+    gtk_text_buffer_get_end_iter(m_pBuffer, &end);
+    gtk_text_buffer_remove_all_tags(m_pBuffer, &start, &end);
+  }
+  void HandleEvent(const Dasher::CEditEvent *pEvt) {
+    const int iPrev(lastCorrectSym());
+    CGameModule::HandleEvent(pEvt);
+    if (iPrev==lastCorrectSym()) {
+      GtkTextIter start,end; //of "wrong" text
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &start, m_mEntered);
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &end, m_mTarget);
+      gtk_text_buffer_delete(m_pBuffer, &start, &end); //invalidates end, brings m_mEntered & m_mTarget together
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &start, m_mEntered);
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &end, m_mTarget);
+      gtk_text_buffer_insert(m_pBuffer, &start, m_strWrong.c_str(), -1); //moves m_mEntered & m_mTarget apart
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &start, m_mEntered);
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &end, m_mTarget);
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &end, m_mTarget);
+      gtk_text_buffer_apply_tag(m_pBuffer, m_tWrong, &start, &end);
+    } else {
+      GtkTextIter it,it2;
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &it, m_mEntered);
+      gtk_text_buffer_get_iter_at_mark(m_pBuffer, &it2, m_mTarget);
+      DASHER_ASSERT(gtk_text_iter_get_offset(&it) == gtk_text_iter_get_offset(&it2));
+      if (iPrev < lastCorrectSym()) {
+        //correct text added
+        DASHER_ASSERT(iPrev == lastCorrectSym()-1);
+        gtk_text_iter_forward_chars(&it2, 1);
+        gtk_text_buffer_apply_tag(m_pBuffer, m_tEntered, &it, &it2);
+      } else {
+        //correct text erased!
+        DASHER_ASSERT(iPrev == lastCorrectSym()+1);
+        gtk_text_iter_backward_chars(&it2, 1);
+        gtk_text_buffer_remove_tag(m_pBuffer, m_tEntered, &it2, &it);
+      }
+      gtk_text_buffer_move_mark(m_pBuffer, m_mEntered, &it2);
+      gtk_text_buffer_move_mark(m_pBuffer, m_mTarget, &it2);
+    } 
+  }
+  void DrawText(CDasherView *pView) {}
+private:
+  GtkTextBuffer *m_pBuffer;
+  GtkTextTag *m_tEntered, *m_tWrong;
+  GtkTextMark *m_mEntered; //just after what's been correctly entered
+  GtkTextMark *m_mTarget; //after any "wrong" text, before target; if no wrong chars, ==m_entered.
+};
+
+CGameModule *CDasherControl::CreateGameModule(CDasherView *pView,CDasherModel *pModel) {
+  if (GtkTextBuffer *buf=gtk_dasher_control_game_text_buffer(m_pDasherControl))
+    return new GtkGameModule(this, this, pView, pModel, buf);
+  return CDashIntfScreenMsgs::CreateGameModule(pView,pModel);
+}
+
 void CDasherControl::ExecuteCommand(const std::string &strCommand) {
     g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_command", strCommand.c_str());
 }
diff --git a/Src/Gtk2/DasherControl.h b/Src/Gtk2/DasherControl.h
index 320630e..803be1f 100644
--- a/Src/Gtk2/DasherControl.h
+++ b/Src/Gtk2/DasherControl.h
@@ -165,6 +165,7 @@ public:
   ///Override to emit Gtk2 signal
   virtual void SetLockStatus(const string &strText, int iPercent);
 
+  CGameModule *CreateGameModule(CDasherView *pView, CDasherModel *pModel);
 private:
   virtual void ScanAlphabetFiles(std::vector<std::string> &vFileList);
   virtual void ScanColourFiles(std::vector<std::string> &vFileList);
diff --git a/Src/Gtk2/GtkDasherControl.cpp b/Src/Gtk2/GtkDasherControl.cpp
index dda6d10..147f78f 100644
--- a/Src/Gtk2/GtkDasherControl.cpp
+++ b/Src/Gtk2/GtkDasherControl.cpp
@@ -28,7 +28,6 @@
 struct _GtkDasherControlPrivate {
   CDasherControl *pControl;
   DasherEditor *pEditor;
-  void* pGameHelper;
 };
 
 typedef struct _GtkDasherControlPrivate GtkDasherControlPrivate;
@@ -125,6 +124,11 @@ void gtk_dasher_control_set_editor(GtkDasherControl *pDasherControl, DasherEdito
   pPrivate->pEditor = pEditor;
 }
 
+GtkTextBuffer *gtk_dasher_control_game_text_buffer(GtkDasherControl *pDasherControl) {
+  GtkDasherControlPrivate *pPrivate = GTK_DASHER_CONTROL_GET_PRIVATE(pDasherControl);
+  return dasher_editor_game_text_buffer(pPrivate->pEditor);
+}
+
 static void 
 gtk_dasher_control_finalize(GObject *pObject) {
   GtkDasherControl *pDasherControl = GTK_DASHER_CONTROL(pObject);
@@ -288,12 +292,6 @@ gtk_dasher_control_get_module_settings(GtkDasherControl * pControl, const gchar
 }
 
 void 
-gtk_dasher_control_game_helperreg(GtkDasherControl *pControl, void* gameHelper) {
-  GtkDasherControlPrivate *pPrivate = GTK_DASHER_CONTROL_GET_PRIVATE(pControl);
-  pPrivate->pGameHelper = gameHelper;
-}
-
-void 
 gtk_dasher_control_force_pause(GtkDasherControl *pControl) {
   GtkDasherControlPrivate *pPrivate = GTK_DASHER_CONTROL_GET_PRIVATE(pControl);
   pPrivate->pControl->Stop();
diff --git a/Src/Gtk2/GtkDasherControl.h b/Src/Gtk2/GtkDasherControl.h
index 612cf23..d7ed426 100644
--- a/Src/Gtk2/GtkDasherControl.h
+++ b/Src/Gtk2/GtkDasherControl.h
@@ -82,7 +82,7 @@ gint gtk_dasher_control_ctrl_delete(GtkDasherControl *pControl, bool bForwards,
 void gtk_dasher_control_external_key_down(GtkDasherControl *pControl, int iKeyVal);
 void gtk_dasher_control_external_key_up(GtkDasherControl *pControl, int iKeyVal);
 gboolean gtk_dasher_control_get_module_settings(GtkDasherControl * pControl, const gchar *szModule, SModuleSettings **pSettings, gint *iCount);
-void gtk_dasher_control_game_helperreg(GtkDasherControl *pControl, void* gameHelper);
+GtkTextBuffer *gtk_dasher_control_game_text_buffer(GtkDasherControl *pPrivate);
 
 void gtk_dasher_control_force_pause(GtkDasherControl *pControl);
 void gtk_dasher_control_add_action_button(GtkDasherControl *pControl, const gchar *szCommand);
diff --git a/Src/Gtk2/dasher_editor.cpp b/Src/Gtk2/dasher_editor.cpp
index 7cf2989..c3201fe 100644
--- a/Src/Gtk2/dasher_editor.cpp
+++ b/Src/Gtk2/dasher_editor.cpp
@@ -212,6 +212,12 @@ dasher_editor_initialise(DasherEditor *pSelf, DasherAppSettings *pAppSettings, D
     DASHER_EDITOR_GET_CLASS(pSelf)->initialise(pSelf, pAppSettings, pDasherMain, pXML, szFullPath);
 }
 
+GtkTextBuffer *dasher_editor_game_text_buffer(DasherEditor *pSelf) {
+  if (DASHER_EDITOR_GET_CLASS(pSelf)->game_text_buffer)
+    return DASHER_EDITOR_GET_CLASS(pSelf)->game_text_buffer(pSelf);
+  return NULL;
+}
+
 void
 dasher_editor_handle_stop(DasherEditor *pSelf) {
   if(DASHER_EDITOR_GET_CLASS(pSelf)->handle_stop)
diff --git a/Src/Gtk2/dasher_editor.h b/Src/Gtk2/dasher_editor.h
index f03cf4d..98c5481 100644
--- a/Src/Gtk2/dasher_editor.h
+++ b/Src/Gtk2/dasher_editor.h
@@ -61,6 +61,8 @@ struct _DasherEditorClass {
   void (*grab_focus)(DasherEditor *);
   gboolean (*file_changed)(DasherEditor *);
   const gchar *(*get_filename)(DasherEditor *);
+  ///Get a buffer to display formatted text for game mode, if we have one
+  GtkTextBuffer *(*game_text_buffer)(DasherEditor *);
 
   /* Signal handlers */
   void (*filename_changed)(DasherEditor *);
@@ -103,6 +105,8 @@ void dasher_editor_action_set_control(DasherEditor *pSelf, int iActionID, bool b
 void dasher_editor_action_set_auto(DasherEditor *pSelf, int iActionID, bool bValue);
 #endif
 
+GtkTextBuffer *dasher_editor_game_text_buffer(DasherEditor *);
+
 void dasher_editor_clear(DasherEditor *pSelf);
 const gchar *dasher_editor_get_all_text(DasherEditor *pSelf);
 const gchar *dasher_editor_get_new_text(DasherEditor *pSelf);
diff --git a/Src/Gtk2/dasher_editor_internal.cpp b/Src/Gtk2/dasher_editor_internal.cpp
index 280c8c5..9caed7b 100644
--- a/Src/Gtk2/dasher_editor_internal.cpp
+++ b/Src/Gtk2/dasher_editor_internal.cpp
@@ -195,6 +195,7 @@ const gchar *dasher_editor_internal_get_filename(DasherEditor *pSelf);
 static void dasher_editor_internal_clear(DasherEditor *pSelf);
 const gchar *dasher_editor_internal_get_all_text(DasherEditor *pSelf);
 const gchar *dasher_editor_internal_get_new_text(DasherEditor *pSelf);
+static GtkTextBuffer *dasher_editor_internal_game_text_buffer(DasherEditor *pEditor);
 
 static void dasher_editor_internal_handle_parameter_change(DasherEditor *pSelf, gint iParameter);
 
@@ -219,6 +220,7 @@ dasher_editor_internal_class_init(DasherEditorInternalClass *pClass) {
 
   DasherEditorClass *pParentClass = (DasherEditorClass *)pClass;
   pParentClass->initialise = dasher_editor_internal_initialise;
+  pParentClass->game_text_buffer = dasher_editor_internal_game_text_buffer;
   pParentClass->command = dasher_editor_internal_command;
   pParentClass->output = dasher_editor_internal_output;
   pParentClass->delete_text = dasher_editor_internal_delete;
@@ -686,10 +688,12 @@ dasher_editor_internal_get_offset(DasherEditor *pSelf) {
 void dasher_editor_internal_mark_changed(DasherEditorInternal *pSelf, GtkTextIter *pIter, GtkTextMark *pMark) {
   const char *szMarkName(gtk_text_mark_get_name(pMark));
   if(szMarkName && !strcmp(szMarkName,"insert")) {
+    DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
     //ACL: used to emit "offset_changed" signal from buffer, which was picked up
     // by a callback registered by editor_internal, which then emitted a context_changed
     // signal from the editor_internal. So just emit the context_changed directly...
-    if (!DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf)->bInControlAction) //tho not if it's the result of a control-mode edit/delete
+    if (!pPrivate->bInControlAction //tho not if it's the result of a control-mode edit/delete
+        && dasher_app_settings_get_bool(pPrivate->pAppSettings, BP_GAME_MODE)) //and not in game mode
       g_signal_emit_by_name(G_OBJECT(pSelf), "context_changed", G_OBJECT(pSelf), NULL, NULL);
   }
 }
@@ -883,13 +887,10 @@ dasher_editor_internal_save_as(DasherEditor *pSelf, const gchar *szFilename, boo
   return true;
 }
 
-// void
-// dasher_editor_internal_start_tutorial(DasherEditor *pSelf) {
-//    DasherEditorInternalPrivate *pPrivate = (DasherEditorInternalPrivate *)(pSelf->private_data);
-
-//   // TODO: reimplement
-//   //  pPrivate->pGameModeHelper = GAME_MODE_HELPER(game_mode_helper_new(GTK_DASHER_CONTROL(pDasherWidget)));
-// }
+GtkTextBuffer *dasher_editor_internal_game_text_buffer(DasherEditor *pSelf) {
+  DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
+  return pPrivate->pBuffer;
+}
 
 gboolean
 dasher_editor_internal_command(DasherEditor *pSelf, const gchar *szCommand) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]