]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/ui.cpp
get the basics of a new scons build system together
[xonotic/netradiant.git] / radiant / ui.cpp
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 //-----------------------------------------------------------------------------\r
23 //\r
24 // DESCRIPTION:\r
25 // implementation of IMessaging specific interface\r
26 // \r
27 \r
28 #include "stdafx.h"\r
29 \r
30 CPtrArray l_Listeners[RADIANT_MSGCOUNT];\r
31 CPtrArray l_WindowListeners;\r
32 CXYWndWrapper l_XYWndWrapper;\r
33 \r
34 // CGtkWindow implementation -------------------------------------\r
35 \r
36 static void button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)\r
37 {\r
38   IWindowListener *pListen = static_cast<IWindowListener *>(data);\r
39   switch (event->button)\r
40   {\r
41   case 1:\r
42     pListen->OnLButtonDown(event->state, event->x, event->y); break;\r
43   case 3:\r
44     pListen->OnRButtonDown(event->state, event->x, event->y); break;\r
45   }\r
46 }\r
47 \r
48 static void button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)\r
49 {\r
50   IWindowListener *pListen = static_cast<IWindowListener *>(data);\r
51   switch (event->button)\r
52   {\r
53   case 1:\r
54     pListen->OnLButtonUp(event->state, event->x, event->y); break;\r
55   case 3:\r
56     pListen->OnRButtonUp(event->state, event->x, event->y); break;\r
57   }\r
58 }\r
59 \r
60 static void motion (GtkWidget *widget, GdkEventMotion *event, gpointer data)\r
61 {\r
62   IWindowListener *pListen = static_cast<IWindowListener *>(data);\r
63   pListen->OnMouseMove(event->state, event->x, event->y);\r
64 }\r
65 \r
66 static gint expose (GtkWidget *widget, GdkEventExpose *event, gpointer data)\r
67 {\r
68   if (event->count > 0)\r
69     return TRUE;\r
70 \r
71   CGtkWindow *pWindow = static_cast<CGtkWindow *>(data);\r
72   pWindow->DoExpose();\r
73 \r
74   return TRUE;\r
75 }\r
76 \r
77 // we use the string versions of the keys for now..\r
78 static gint keypress (GtkWidget* widget, GdkEventKey* event, gpointer data)\r
79 {\r
80   gint ret;\r
81 \r
82   IWindowListener *pListen = static_cast<IWindowListener *>(data);\r
83   ret = pListen->OnKeyPressed(gdk_keyval_name(event->keyval));\r
84   if (ret)\r
85   {\r
86     gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");\r
87   }\r
88   return ret;\r
89 }\r
90 \r
91 // close_widget is not hooked on the listener but on the CGtkWindow object to handle the closure\r
92 static gint close_widget (GtkWidget *widget, GdkEvent* event, gpointer data)\r
93 {\r
94   CGtkWindow *pWindow = static_cast<CGtkWindow *>(data);\r
95   pWindow->Close();\r
96 \r
97   return TRUE;\r
98 }\r
99 \r
100 void CGtkWindow::DoExpose()\r
101 {\r
102   gtk_glwidget_make_current(m_pGLWidget);\r
103   if (m_pListen->Paint())\r
104     gtk_glwidget_swap_buffers(m_pGLWidget);\r
105 }\r
106 \r
107 void CGtkWindow::Redraw()\r
108 {\r
109   gtk_widget_queue_draw(m_pGLWidget);\r
110 }\r
111 \r
112 void CGtkWindow::Close()\r
113 {\r
114   // similar to a destructor, except we warn first\r
115   m_pListen->Close();\r
116   m_pListen->DecRef(); m_pListen = NULL;\r
117   gtk_widget_destroy(m_pWnd); m_pWnd = NULL;\r
118 }\r
119 \r
120 bool CGtkWindow::Show()\r
121 {\r
122   // check we got everything and are reading to instanciate\r
123   if (m_nWidthParam == 0 || m_nHeightParam == 0)\r
124   {\r
125     Sys_FPrintf(SYS_ERR, "Height and Width params not set in CGtkWindow::Show\n");\r
126     return false;\r
127   }\r
128   if (!m_pListen)\r
129   {\r
130     Sys_FPrintf(SYS_ERR, "No listener set in CGtkWindow::Show\n");\r
131     return false;\r
132   }\r
133 \r
134   // seems all good, here we go\r
135   m_pWnd = gtk_window_new (GTK_WINDOW_TOPLEVEL);\r
136   gtk_window_set_title (GTK_WINDOW (m_pWnd), m_Name.GetBuffer());\r
137   gtk_window_set_default_size (GTK_WINDOW (m_pWnd), m_nWidthParam, m_nHeightParam);\r
138   gtk_widget_show (m_pWnd);\r
139 \r
140   // GL widget creation\r
141   m_pGLWidget = gtk_glwidget_new(FALSE, g_qeglobals_gui.d_glBase);\r
142 \r
143   gtk_widget_set_events (m_pGLWidget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |\r
144                          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);\r
145 \r
146   // Connect signal handlers\r
147   gtk_signal_connect (GTK_OBJECT (m_pGLWidget), "expose_event", GTK_SIGNAL_FUNC (expose), this);\r
148   gtk_signal_connect (GTK_OBJECT (m_pGLWidget), "motion_notify_event",\r
149                       GTK_SIGNAL_FUNC (motion), m_pListen);\r
150   gtk_signal_connect (GTK_OBJECT (m_pGLWidget), "button_press_event",\r
151                       GTK_SIGNAL_FUNC (button_press), m_pListen);\r
152   gtk_signal_connect (GTK_OBJECT (m_pGLWidget), "button_release_event",\r
153                       GTK_SIGNAL_FUNC (button_release), m_pListen);\r
154 \r
155   gtk_signal_connect (GTK_OBJECT (m_pWnd), "delete_event", GTK_SIGNAL_FUNC (close_widget), this);\r
156   gtk_signal_connect (GTK_OBJECT (m_pWnd), "key_press_event",\r
157                       GTK_SIGNAL_FUNC (keypress), m_pListen);\r
158 \r
159   gtk_widget_show (m_pGLWidget);\r
160   gtk_container_add (GTK_CONTAINER (m_pWnd), m_pGLWidget);\r
161 \r
162   return true;\r
163 }\r
164 \r
165 IWindow* WINAPI QERApp_CreateGLWindow()\r
166 {\r
167   return new CGtkWindow;\r
168 }\r
169 \r
170 void WINAPI QERApp_HookWindow(IWindowListener* pListen)\r
171 {\r
172   l_WindowListeners.Add( pListen );\r
173   pListen->IncRef();\r
174 }\r
175 \r
176 void WINAPI QERApp_UnHookWindow(IWindowListener* pListen)\r
177 {\r
178   for ( int i = 0; i < l_WindowListeners.GetSize(); i++ )\r
179   {\r
180     if (l_WindowListeners.GetAt(i) == pListen)\r
181     {\r
182       l_WindowListeners.RemoveAt(i);\r
183       pListen->DecRef();\r
184       return;\r
185     }\r
186   }\r
187 #ifdef _DEBUG\r
188   Sys_Printf("WARNING: IWindowListener not found in QERApp_UnHookWindow\n");\r
189 #endif\r
190 }\r
191 \r
192 void DispatchOnMouseMove(guint32 nFlags, int x, int y)\r
193 {\r
194   for( int i = 0; i < l_WindowListeners.GetSize(); i++ )\r
195     static_cast<IWindowListener*>(l_WindowListeners.GetAt(i))->OnMouseMove( nFlags, x, y );\r
196 }\r
197 \r
198 bool DispatchOnLButtonDown(guint32 nFlags, int x, int y)\r
199 {\r
200   for( int i = 0; i < l_WindowListeners.GetSize(); i++ )\r
201     if (static_cast<IWindowListener*>(l_WindowListeners.GetAt(i))->OnLButtonDown( nFlags, x, y ))\r
202       return true;\r
203   return false;\r
204 }\r
205 \r
206 bool DispatchOnLButtonUp(guint32 nFlags, int x, int y)\r
207 {\r
208   for( int i = 0; i < l_WindowListeners.GetSize(); i++ )\r
209     if (static_cast<IWindowListener*>(l_WindowListeners.GetAt(i))->OnLButtonUp( nFlags, x, y ))\r
210       return true;\r
211   return false;\r
212 }\r
213 \r
214 void WINAPI QERApp_HookListener(IListener* pListen, int Msg)\r
215 {\r
216 #ifdef _DEBUG\r
217   if (Msg >= RADIANT_MSGCOUNT)\r
218   {\r
219     Sys_Printf("ERROR: bad index in QERApp_HookListener\n");\r
220     return;\r
221   }\r
222 #endif\r
223   l_Listeners[Msg].Add( pListen );\r
224   pListen->IncRef();\r
225 }\r
226 \r
227 int  WINAPI QERApp_UnHookListener(IListener* pListen)\r
228 {\r
229   int count = 0;\r
230   for( int i = 0; i<RADIANT_MSGCOUNT; i++ )\r
231     for( int j = 0; j<l_Listeners[i].GetSize(); j++ )\r
232       if (l_Listeners[i].GetAt(j) == pListen)\r
233       {\r
234         l_Listeners[i].RemoveAt(j);\r
235         pListen->DecRef();\r
236         count++;\r
237       }\r
238   return count;\r
239 }\r
240 \r
241 void DispatchRadiantMsg( int Msg )\r
242 {\r
243 #ifdef _DEBUG\r
244   if (Msg >= RADIANT_MSGCOUNT)\r
245   {\r
246     Sys_Printf("ERROR: bad index in DispatchRadiantMsg\n");\r
247     return;\r
248   }\r
249 #endif\r
250   for(int i = 0; i<l_Listeners[Msg].GetSize(); i++)\r
251     static_cast<IListener *>(l_Listeners[Msg].GetAt(i))->DispatchRadiantMsg(Msg);\r
252 }\r
253 \r
254 void CXYWndWrapper::SnapToGrid( int x1, int y1, vec3_t pt )\r
255 {\r
256   int height = g_pParentWnd->ActiveXY()->GetWidget()->allocation.height;\r
257   g_pParentWnd->ActiveXY()->SnapToPoint( x1, height - 1 - y1, pt );\r
258 }\r
259 \r
260 VIEWTYPE CXYWndWrapper::GetViewType( void )\r
261 {\r
262   return (VIEWTYPE)g_pParentWnd->ActiveXY()->GetViewType();\r
263 }\r
264 \r
265 IXYWndWrapper* WINAPI QERApp_GetXYWndWrapper()\r
266 {\r
267   return &l_XYWndWrapper;\r
268 }\r