1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "tools/edit_gui_common.h"
30 
31 
32 #include "../../sys/win32/rc/guied_resource.h"
33 #include "../../renderer/tr_local.h"
34 #include "../../sys/win32/win_local.h"
35 #include "../../ui/DeviceContext.h"
36 #include "../../ui/EditWindow.h"
37 #include "../../ui/ListWindow.h"
38 #include "../../ui/BindWindow.h"
39 #include "../../ui/RenderWindow.h"
40 #include "../../ui/ChoiceWindow.h"
41 
42 #include "GEApp.h"
43 #include "GEItemPropsDlg.h"
44 #include "GEItemScriptsDlg.h"
45 
46 // Modifiers
47 #include "GEModifierGroup.h"
48 #include "GEMoveModifier.h"
49 #include "GESizeModifier.h"
50 #include "GEStateModifier.h"
51 #include "GEZOrderModifier.h"
52 #include "GEInsertModifier.h"
53 #include "GEHideModifier.h"
54 #include "GEDeleteModifier.h"
55 
56 static float g_ZoomScales[rvGEWorkspace::ZOOM_MAX] = { 0, 0.25f, 0.33f, 0.50f, 0.66f, 1.0f, 1.5f, 2.0f, 3.0f };
57 
58 static const int ID_GUIED_SELECT_FIRST = 9800;
59 static const int ID_GUIED_SELECT_LAST  = 9900;
60 
61 idList<rvGEClipboardItem*> rvGEWorkspace::mClipboard;
62 
rvGEWorkspace(rvGEApp * app)63 rvGEWorkspace::rvGEWorkspace ( rvGEApp* app ) : mApplication ( app )
64 {
65 	mWnd				= 0;
66 	mInterface			= 0;
67 	mZoom				= ZOOM_100;
68 	mScrollHorz			= false;
69 	mScrollVert			= false;
70 	mModified			= false;
71 	mNew				= false;
72 	mDragScroll			= false;
73 	mSourceControlState = SCS_CHECKEDOUT;
74 	mFilename			= "guis/Untitled.gui";
75 	mDragType			= rvGESelectionMgr::HT_NONE;
76 	mHandCursor			= LoadCursor ( app->GetInstance(), MAKEINTRESOURCE(IDC_GUIED_HAND) );
77 	mDontAdd			= false;
78 
79 	mSelections.SetWorkspace ( this );
80 }
81 
~rvGEWorkspace()82 rvGEWorkspace::~rvGEWorkspace ( )
83 {
84 	// Make sure all the wrappers get cleaned up
85 	rvGEWindowWrapper::GetWrapper ( mInterface->GetDesktop ( ) )->EnumChildren ( CleanupEnumProc, NULL );
86 
87 	DestroyCursor ( mHandCursor );
88 
89 	delete mInterface;
90 }
91 
92 /*
93 ================
94 rvGEWorkspace::CleanupEnumProc
95 
96 Window enumeration procedure that deletes all the wrapper classes
97 ================
98 */
CleanupEnumProc(rvGEWindowWrapper * wrapper,void * data)99 bool rvGEWorkspace::CleanupEnumProc ( rvGEWindowWrapper* wrapper, void* data )
100 {
101 	bool result;
102 
103 	if ( !wrapper )
104 	{
105 		return true;
106 	}
107 
108 	result = wrapper->EnumChildren ( CleanupEnumProc, data );
109 
110 	// Cleanup the window wrapper
111 	delete wrapper;
112 
113 	return result;
114 }
115 
116 /*
117 ================
118 rvGEWorkspace::GetZoomScale
119 
120 Returns the scale of the current zoom level
121 ================
122 */
GetZoomScale(void)123 float rvGEWorkspace::GetZoomScale ( void )
124 {
125 	return g_ZoomScales [ mZoom ];
126 }
127 
128 /*
129 ================
130 rvGEWorkspace::Attach
131 
132 Attaches the workspace to the given window.  This is usually done after the
133 window is created and the file has been loaded.
134 ================
135 */
Attach(HWND wnd)136 bool rvGEWorkspace::Attach ( HWND wnd )
137 {
138 	assert ( wnd );
139 
140 	mWnd = wnd;
141 
142 	// Initialize the pixel format for this window
143 	SetupPixelFormat ( );
144 
145 	// Jam the workspace pointer into the userdata window long so
146 	// we can retrieve the workspace from the window later
147 	SetWindowLong ( mWnd, GWL_USERDATA, (LONG) this );
148 
149 	UpdateTitle ( );
150 
151 	return true;
152 }
153 
154 /*
155 ================
156 rvGEWorkspace::Detach
157 
158 Detaches the workspace from the window it is currently attached to
159 ================
160 */
Detach(void)161 void rvGEWorkspace::Detach ( void )
162 {
163 	assert ( mWnd );
164 
165 	SetWindowLong ( mWnd, GWL_USERDATA, 0 );
166 	mWnd = NULL;
167 }
168 
169 /*
170 ================
171 rvGEWorkspace::SetupPixelFormat
172 
173 Setup the pixel format for the opengl context
174 ================
175 */
SetupPixelFormat(void)176 bool rvGEWorkspace::SetupPixelFormat ( void )
177 {
178 	HDC	 hDC    = GetDC ( mWnd );
179 	bool result = true;
180 
181 	int pixelFormat = ChoosePixelFormat(hDC, &win32.pfd);
182 	if (pixelFormat > 0)
183 	{
184 		if (SetPixelFormat(hDC, pixelFormat, &win32.pfd) == NULL)
185 		{
186 			result = false;
187 		}
188 	}
189 	else
190 	{
191 		result = false;
192 	}
193 
194 	ReleaseDC ( mWnd, hDC );
195 
196 	return result;
197 }
198 
199 /*
200 ================
201 rvGEWorkspace::RenderGrid
202 
203 Renders the grid on top of the user interface
204 ================
205 */
RenderGrid(void)206 void rvGEWorkspace::RenderGrid ( void )
207 {
208 	float	x;
209 	float	y;
210 	float	step;
211 	idVec4&	color = mApplication->GetOptions().GetGridColor ( );
212 
213 	// See if the grid is off before rendering it
214 	if ( !mApplication->GetOptions().GetGridVisible ( ))
215 	{
216 		return;
217 	}
218 
219 	qglEnable(GL_BLEND);
220 	qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
221 
222 	qglColor4f ( color[0], color[1], color[2], 0.5f );
223 
224 	qglBegin ( GL_LINES );
225 	step = mApplication->GetOptions().GetGridWidth ( ) * g_ZoomScales[mZoom];
226 	for ( x = mRect.x + mRect.w; x >= mRect.x ; x -= step )
227 	{
228 		qglVertex2f ( x, mRect.y );
229 		qglVertex2f ( x, mRect.y + mRect.h );
230 	}
231 	step = mApplication->GetOptions().GetGridHeight ( ) * g_ZoomScales[mZoom];
232 	for ( y = mRect.y + mRect.h; y >= mRect.y ; y -= step )
233 	{
234 		qglVertex2f ( mRect.x, y );
235 		qglVertex2f ( mRect.x + mRect.w, y );
236 	}
237 	qglEnd ( );
238 
239 	qglDisable(GL_BLEND);
240 	qglColor3f ( color[0], color[1], color[2] );
241 
242 	qglBegin ( GL_LINES );
243 	step = mApplication->GetOptions().GetGridWidth ( ) * g_ZoomScales[mZoom];
244 	for ( x = mRect.x + mRect.w; x >= mRect.x ; x -= step * 4 )
245 	{
246 		qglVertex2f ( x, mRect.y );
247 		qglVertex2f ( x, mRect.y + mRect.h );
248 	}
249 	step = mApplication->GetOptions().GetGridHeight ( ) * g_ZoomScales[mZoom];
250 	for ( y = mRect.y + mRect.h; y >= mRect.y ; y -= step * 4 )
251 	{
252 		qglVertex2f ( mRect.x, y );
253 		qglVertex2f ( mRect.x + mRect.w, y );
254 	}
255 	qglEnd ( );
256 }
257 
258 /*
259 ================
260 rvGEWorkspace::Render
261 
262 Renders the workspace to the given DC
263 ================
264 */
Render(HDC hdc)265 void rvGEWorkspace::Render ( HDC hdc )
266 {
267 	int		front;
268 	int		back;
269 	float	scale;
270 
271 	scale = g_ZoomScales[mZoom];
272 
273 	// Switch GL contexts to our dc
274 	if (!qwglMakeCurrent( hdc, win32.hGLRC ))
275 	{
276 		common->Printf("ERROR: wglMakeCurrent failed.. Error:%i\n", qglGetError());
277 		common->Printf("Please restart Q3Radiant if the Map view is not working\n");
278 		return;
279 	}
280 
281 	// Prepare the view and clear it
282 	GL_State( GLS_DEFAULT );
283 	qglViewport(0, 0, mWindowWidth, mWindowHeight );
284 	qglScissor(0, 0, mWindowWidth, mWindowHeight );
285 	qglClearColor ( 0.75f, 0.75f, 0.75f, 0 );
286 
287 	qglDisable(GL_DEPTH_TEST);
288 	qglDisable(GL_CULL_FACE);
289 	qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
290 
291 	// Render the workspace below
292 	qglMatrixMode(GL_PROJECTION);
293 	qglLoadIdentity();
294 	qglOrtho(0,mWindowWidth, mWindowHeight, 0, -1, 1);
295 	qglMatrixMode(GL_MODELVIEW);
296 	qglLoadIdentity();
297 
298 	qglColor3f ( mApplication->GetOptions().GetWorkspaceColor()[0], mApplication->GetOptions().GetWorkspaceColor()[1], mApplication->GetOptions().GetWorkspaceColor()[2] );
299 	qglBegin ( GL_QUADS );
300 	qglVertex2f ( mRect.x, mRect.y );
301 	qglVertex2f ( mRect.x + mRect.w, mRect.y );
302 	qglVertex2f ( mRect.x + mRect.w, mRect.y + mRect.h );
303 	qglVertex2f ( mRect.x, mRect.y + mRect.h );
304 	qglEnd ( );
305 
306 	// Prepare the renderSystem view to draw the GUI in
307 	viewDef_t viewDef;
308 	memset ( &viewDef, 0, sizeof(viewDef) );
309 	tr.viewDef = &viewDef;
310 	tr.viewDef->renderView.x = mRect.x;
311 	tr.viewDef->renderView.y = mWindowHeight - mRect.y - mRect.h;
312 	tr.viewDef->renderView.width = mRect.w;
313 	tr.viewDef->renderView.height = mRect.h;
314 	tr.viewDef->scissor.x1 = 0;
315 	tr.viewDef->scissor.y1 = 0;
316 	tr.viewDef->scissor.x2 = mRect.w;
317 	tr.viewDef->scissor.y2 = mRect.h;
318 	tr.viewDef->isEditor = true;
319 	renderSystem->BeginFrame(mWindowWidth, mWindowHeight );
320 
321 	// Draw the gui
322 	mInterface->Redraw ( 0 ); // eventLoop->Milliseconds() );
323 
324 	// We are done using the renderSystem now
325 	renderSystem->EndFrame( &front, &back );
326 
327 	if ( mApplication->GetActiveWorkspace ( ) == this )
328 	{
329 		mApplication->GetStatusBar().SetTriangles ( backEnd.pc.c_drawIndexes/3 );
330 	}
331 
332 	// Prepare the viewport for drawing selections, etc.
333 	GL_State( GLS_DEFAULT );
334 	qglDisable( GL_TEXTURE_CUBE_MAP_EXT );
335 //	qglDisable(GL_BLEND);
336 	qglDisable(GL_CULL_FACE);
337 
338 	qglViewport(0, 0, mWindowWidth, mWindowHeight );
339 	qglScissor(0, 0, mWindowWidth, mWindowHeight );
340 	qglMatrixMode(GL_PROJECTION);
341 	qglLoadIdentity();
342 	qglOrtho(0,mWindowWidth, mWindowHeight, 0, -1, 1);
343 	qglMatrixMode(GL_MODELVIEW);
344 	qglLoadIdentity();
345 
346 	RenderGrid ( );
347 
348 	mSelections.Render ( );
349 
350 	qglFinish ( );
351 	qwglSwapBuffers(hdc);
352 
353 	qglEnable( GL_TEXTURE_CUBE_MAP_EXT );
354 	qglEnable( GL_CULL_FACE);
355 }
356 
357 /*
358 ================
359 rvGEWorkspace::UpdateTitle
360 
361 Updates the window title with the name of the file and the zoom level and weither its open or not
362 ================
363 */
UpdateTitle(void)364 void rvGEWorkspace::UpdateTitle ( void )
365 {
366 	// Set the window title based on the current filename
367 	SetWindowText ( mWnd, va("%s%s (%d%%)", idStr(mFilename).StripPath ( ).c_str( ), mModified?"*":"", (int) (g_ZoomScales[mZoom] * 100)) );
368 
369 	gApp.GetStatusBar().SetZoom ( (int)(g_ZoomScales[mZoom] * 100.0f) );
370 }
371 
372 /*
373 ================
374 rvGEWorkspace::UpdateRectangle
375 
376 Updates the rectangle (not counting scrolling)
377 ================
378 */
UpdateRectangle(bool useScroll)379 void rvGEWorkspace::UpdateRectangle ( bool useScroll )
380 {
381 	RECT	rcClient;
382 	float	x;
383 	float	y;
384 	float	scale;
385 
386 	scale = g_ZoomScales[mZoom];
387 
388 	// Grab the current client rectangle of the window and cache off the width and height
389 	GetClientRect ( mWnd, &rcClient );
390 	mWindowWidth = rcClient.right - rcClient.left;
391 	mWindowHeight = rcClient.bottom - rcClient.top;
392 
393 	// The workspace is always centered in the window
394 	x = mRect.x = mWindowWidth / 2 - (SCREEN_WIDTH * scale) / 2;
395 	y = mRect.y = mWindowHeight / 2 - (SCREEN_HEIGHT * scale) / 2;
396 	mRect.w = (SCREEN_WIDTH * scale);
397 	mRect.h = (SCREEN_HEIGHT * scale);
398 
399 	// When using the scroll position offset the rectangle based on the scrollbar positions
400 	if ( useScroll )
401 	{
402 		// Adjust the start of the rectangle for the scroll positiond
403 		mRect.y -= (float)GetScrollPos ( mWnd, SB_VERT ) / 1000.0f;
404 		mRect.x -= (float)GetScrollPos ( mWnd, SB_HORZ ) / 1000.0f;
405 	}
406 }
407 
408 /*
409 ================
410 rvGEWorkspace::Scroll
411 
412 Adjusts the given scrollbar by the given offset
413 ================
414 */
Scroll(int scrollbar,int offset)415 void rvGEWorkspace::Scroll ( int scrollbar, int offset )
416 {
417 	SCROLLINFO si;
418 
419 	if ( scrollbar == SB_HORZ && !mScrollHorz )
420 	{
421 		return;
422 	}
423 	else if ( scrollbar == SB_VERT && !mScrollVert )
424 	{
425 		return;
426 	}
427 
428 	// Get all the vertial scroll bar information
429 	si.cbSize = sizeof (si);
430 	si.fMask  = SIF_ALL;
431 
432 	// Save the position for comparison later on
433 	GetScrollInfo ( mWnd, scrollbar, &si);
434 
435 	si.nPos += (1000 * offset);
436 	if ( si.nPos < si.nMin ) si.nPos = si.nMin;
437 	if ( si.nPos > si.nMax ) si.nPos = si.nMax;
438 
439 	si.fMask = SIF_POS;
440 	SetScrollInfo (mWnd, scrollbar, &si, TRUE);
441 	GetScrollInfo (mWnd, scrollbar, &si);
442 
443 	UpdateRectangle ( );
444 }
445 
HandleScroll(int scrollbar,WPARAM wParam,LPARAM lParam)446 int rvGEWorkspace::HandleScroll ( int scrollbar, WPARAM wParam, LPARAM lParam )
447 {
448 	SCROLLINFO si;
449 
450 	// Get all the vertial scroll bar information
451 	si.cbSize = sizeof (si);
452 	si.fMask  = SIF_ALL;
453 
454 	// Save the position for comparison later on
455 	GetScrollInfo ( mWnd, scrollbar, &si);
456 
457 	switch (LOWORD (wParam))
458 	{
459 		// user clicked left or up arrow
460 		case SB_LINELEFT:
461 			si.nPos -= 1000;
462 			break;
463 
464 		// user clicked right or down arrow
465 		case SB_LINERIGHT:
466 			si.nPos += 1000;
467 			break;
468 
469 		// user clicked shaft left of the scroll box
470 		case SB_PAGELEFT:
471 			si.nPos -= si.nPage;
472 			break;
473 
474 		// user clicked shaft right of the scroll box
475 		case SB_PAGERIGHT:
476 			si.nPos += si.nPage;
477 			break;
478 
479 		// user dragged the scroll box
480 		case SB_THUMBTRACK:
481 			si.nPos = si.nTrackPos;
482 			break;
483 
484 		default :
485 			break;
486 	}
487 
488 	// Set the position and then retrieve it.  Due to adjustments
489 	//   by Windows it may not be the same as the value set.
490 	si.fMask = SIF_POS;
491 	SetScrollInfo (mWnd, scrollbar, &si, TRUE);
492 	GetScrollInfo (mWnd, scrollbar, &si);
493 
494 	UpdateRectangle ( );
495 
496 	return 0;
497 }
498 
499 /*
500 ================
501 rvGEWorkspace::UpdateScrollbars
502 
503 Updates the states and the ranges of the scrollbars as well as the rectangle
504 ================
505 */
UpdateScrollbars(void)506 void rvGEWorkspace::UpdateScrollbars ( void )
507 {
508 	SCROLLINFO info;
509 
510 	// First update the rectangle without applying scroll positions so
511 	// we know the real sizes and coordinates
512 	UpdateRectangle ( false );
513 
514 	// Setup the veritcal scrollbar
515 	info.cbSize = sizeof(info);
516 	info.fMask = SIF_RANGE|SIF_PAGE;
517 	info.nMax = (mRect.h - mWindowHeight + 10) * 1000 / 2;
518 	info.nMin = -info.nMax;
519 	info.nPage = (int)((float)info.nMax * (float)((float)mWindowHeight / mRect.h));
520 	info.nMax += info.nPage;
521 
522 	// If there is something to scroll then turn on the vertical scroll bar
523 	// if its not on and update the scroll info.
524 	if ( info.nMax > 0 )
525 	{
526 		if ( !mScrollVert )
527 		{
528 			mScrollVert = true;
529 			ShowScrollBar ( mWnd, SB_VERT, mScrollVert );
530 		}
531 		SetScrollInfo ( mWnd, SB_VERT, &info, TRUE );
532 	}
533 	// Nothing to scroll, turn off the scrollbar if its on.
534 	else if ( mScrollVert )
535 	{
536 		mScrollVert = false;
537 		SetScrollPos ( mWnd, SB_VERT, 0, FALSE );
538 		ShowScrollBar ( mWnd, SB_VERT, mScrollVert );
539 	}
540 
541 	// Setup the horizontal scrollbar
542 	info.nMax = (mRect.w - mWindowWidth + 10) * 1000 / 2;
543 	info.nMin = -info.nMax;
544 	info.nPage = (int)((float)info.nMax * (float)((float)mWindowWidth / mRect.w));
545 	info.nMax += info.nPage;
546 
547 	// If there is something to scroll then turn on the vertical scroll bar
548 	// if its not on and update the scroll info.
549 	if ( info.nMax > 0 )
550 	{
551 		if ( !mScrollHorz )
552 		{
553 			mScrollHorz = true;
554 			ShowScrollBar ( mWnd, SB_HORZ, mScrollHorz );
555 		}
556 
557 		SetScrollInfo ( mWnd, SB_HORZ, &info, TRUE );
558 	}
559 	// Nothing to scroll, turn off the scrollbar if its on.
560 	else if ( mScrollHorz )
561 	{
562 		mScrollHorz = false;
563 		SetScrollPos ( mWnd, SB_HORZ, 0, FALSE );
564 		ShowScrollBar ( mWnd, SB_HORZ, mScrollHorz );
565 	}
566 
567 	// Need to update the rectangle again to take the scrollbar changes into account
568 	UpdateRectangle ( true );
569 }
570 
571 /*
572 ================
573 rvGEWorkspace::UpdateCursor
574 
575 Called to update the cursor when the mouse is within the workspace window
576 ================
577 */
UpdateCursor(rvGESelectionMgr::EHitTest type)578 void rvGEWorkspace::UpdateCursor ( rvGESelectionMgr::EHitTest type )
579 {
580 	switch ( type )
581 	{
582 		case rvGESelectionMgr::HT_SELECT:
583 			SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_ARROW) ) );
584 			break;
585 
586 		case rvGESelectionMgr::HT_MOVE:
587 			SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_SIZEALL) ) );
588 			break;
589 
590 		case rvGESelectionMgr::HT_SIZE_LEFT:
591 		case rvGESelectionMgr::HT_SIZE_RIGHT:
592 			SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_SIZEWE ) ) );
593 			break;
594 
595 		case rvGESelectionMgr::HT_SIZE_TOP:
596 		case rvGESelectionMgr::HT_SIZE_BOTTOM:
597 			SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_SIZENS ) ) );
598 			break;
599 
600 		case rvGESelectionMgr::HT_SIZE_TOPRIGHT:
601 		case rvGESelectionMgr::HT_SIZE_BOTTOMLEFT:
602 			SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_SIZENESW ) ) );
603 			break;
604 
605 		case rvGESelectionMgr::HT_SIZE_BOTTOMRIGHT:
606 		case rvGESelectionMgr::HT_SIZE_TOPLEFT:
607 			SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_SIZENWSE ) ) );
608 			break;
609 	}
610 }
611 
UpdateCursor(float x,float y)612 void rvGEWorkspace::UpdateCursor ( float x, float y )
613 {
614 	idVec2						point;
615 	rvGESelectionMgr::EHitTest	type;
616 
617 	// First convert the worspace coord to a window coord
618 	point = WorkspaceToWindow ( idVec2( x, y ) );
619 
620 	// See if it hits anything
621 	type = mSelections.HitTest ( point.x, point.y );
622 
623 	// If it hits something then use it to update the cursor
624 	if ( rvGESelectionMgr::HT_NONE != type )
625 	{
626 		UpdateCursor ( type );
627 	}
628 	else
629 	{
630 		SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_ARROW ) ) );
631 	}
632 }
633 
UpdateCursor(void)634 void rvGEWorkspace::UpdateCursor ( void )
635 {
636 	if ( mDragType == rvGESelectionMgr::HT_NONE )
637 	{
638 		POINT	point;
639 		idVec2	cursor;
640 
641 		GetCursorPos ( &point );
642 		cursor.Set ( point.x, point.y );
643 		WindowToWorkspace ( cursor );
644 
645 		UpdateCursor ( cursor.x, cursor.y );
646 	}
647 	else
648 	{
649 		UpdateCursor ( mDragType );
650 	}
651 }
652 
653 /*
654 ================
655 rvGEWorkspace::HandleMessage
656 
657 Handles window messages to the workspace
658 ================
659 */
HandleMessage(UINT msg,WPARAM wParam,LPARAM lParam)660 void rvGEWorkspace::HandleMessage ( UINT msg, WPARAM wParam, LPARAM lParam )
661 {
662 	switch ( msg )
663 	{
664 		case WM_CLOSE:
665 		{
666 
667 			if ( IsModified ( ) )
668 			{
669 				if ( IDYES == gApp.MessageBox ( va("Save changes to the document \"%s\" before closing?", GetFilename() ), MB_YESNO|MB_ICONQUESTION ) )
670 				{
671 					SendMessage ( mApplication->GetMDIFrame(), WM_COMMAND, MAKELONG(ID_GUIED_FILE_SAVE,0), 0 );
672 				}
673 			}
674 
675 
676 			GetApplication ( )->GetNavigator().SetWorkspace(NULL);
677 			GetApplication ( )->GetTransformer().SetWorkspace(NULL);
678 			GetApplication ( )->GetProperties().SetWorkspace(NULL);
679 			break;
680 		}
681 
682 		case WM_CAPTURECHANGED:
683 			if ( (HWND)lParam != mWnd )
684 			{
685 				mDragScroll = false;
686 				mDragType	= rvGESelectionMgr::HT_NONE;
687 			}
688 			break;
689 
690 		case WM_SETCURSOR:
691 		{
692 			POINT point;
693 			idVec2 cursor;
694 			GetCursorPos ( &point );
695 			cursor.Set ( point.x, point.y );
696 			WindowToWorkspace ( cursor );
697 			if ( mDragType == rvGESelectionMgr::HT_NONE )
698 			{
699 				UpdateCursor ( cursor.x, cursor.y );
700 			}
701 			else
702 			{
703 				UpdateCursor ( mDragType );
704 			}
705 			break;
706 		}
707 
708 		case WM_MOUSEWHEEL:
709 			if ( (short)HIWORD(wParam) > 0 )
710 			{
711 				ZoomIn ( );
712 			}
713 			else if ( (short)HIWORD(wParam) < 0 )
714 			{
715 				ZoomOut ( );
716 			}
717 			break;
718 
719 		case WM_MOUSEMOVE:
720 			HandleMouseMove ( wParam, lParam );
721 			break;
722 
723 		case WM_MBUTTONDOWN:
724 			HandleMButtonDown ( wParam, lParam );
725 			break;
726 
727 		case WM_MBUTTONUP:
728 			HandleMButtonUp ( wParam, lParam );
729 			break;
730 
731 		case WM_LBUTTONDOWN:
732 			HandleLButtonDown ( wParam, lParam );
733 			break;
734 
735 		case WM_LBUTTONUP:
736 			HandleLButtonUp ( wParam, lParam );
737 			break;
738 
739 		case WM_LBUTTONDBLCLK:
740 			HandleLButtonDblClk ( wParam, lParam );
741 			break;
742 
743 		case WM_INITMENUPOPUP:
744 			SendMessage ( mApplication->GetMDIFrame(), msg, wParam, lParam );
745 			break;
746 
747 		case WM_COMMAND:
748 			HandleCommand ( wParam, lParam );
749 			break;
750 
751 		case WM_RBUTTONDOWN:
752 			HandleRButtonDown ( wParam, lParam );
753 			break;
754 
755 		case WM_SIZE:
756 			UpdateScrollbars();
757 			break;
758 
759 		case WM_VSCROLL:
760 			HandleScroll ( SB_VERT, wParam, lParam );
761 			break;
762 
763 		case WM_HSCROLL:
764 			HandleScroll ( SB_HORZ, wParam, lParam );
765 			break;
766 
767 		case WM_KEYDOWN:
768 			HandleKeyDown ( wParam, lParam );
769 			break;
770 	}
771 }
772 /*
773 ================
774 rvGEWorkspace::HandleCommand
775 
776 Handles command messages destined for the workspace window.  This is for
777 special workspace commands, any unhandled commands are forwarded to the main window
778 ================
779 */
HandleCommand(WPARAM wParam,LPARAM lParam)780 int	rvGEWorkspace::HandleCommand ( WPARAM wParam, LPARAM lParam )
781 {
782 	// Select command
783 	if ( LOWORD(wParam) >= ID_GUIED_SELECT_FIRST && LOWORD(wParam) <= ID_GUIED_SELECT_LAST )
784 	{
785 		idWindow*			window  = mSelectMenu[LOWORD(wParam)-ID_GUIED_SELECT_FIRST];
786 		rvGEWindowWrapper*	wrapper = rvGEWindowWrapper::GetWrapper ( window );
787 
788 		// Handle multi select as well
789 		if ( GetAsyncKeyState ( VK_SHIFT ) & 0x8000 )
790 		{
791 			if ( wrapper->IsSelected ( ) )
792 			{
793 				mSelections.Remove ( window );
794 			}
795 			else
796 			{
797 				mSelections.Add ( window );
798 			}
799 		}
800 		else
801 		{
802 			mSelections.Set ( window );
803 		}
804 	}
805 
806 	return SendMessage ( mApplication->GetMDIFrame(), WM_COMMAND, wParam, lParam );
807 }
808 
809 /*
810 ================
811 rvGEWorkspace::HandleMButtonDown
812 
813 Handles the middle mouse down message in the workspace
814 ================
815 */
HandleMButtonDown(WPARAM wParam,LPARAM lParam)816 int	rvGEWorkspace::HandleMButtonDown ( WPARAM wParam, LPARAM lParam )
817 {
818 	if ( mDragType != rvGESelectionMgr::HT_NONE )
819 	{
820 		return 0;
821 	}
822 
823 	mDragPoint.Set ( LOWORD(lParam), HIWORD(lParam) );
824 	mDragScroll = true;
825 	SetCursor ( mHandCursor );
826 	SetCapture ( mWnd );
827 
828 	WindowToWorkspace ( mDragPoint );
829 
830 	return 0;
831 }
832 
833 /*
834 ================
835 rvGEWorkspace::HandleMButtonUp
836 
837 Handles the middle mouse up message in the workspace
838 ================
839 */
HandleMButtonUp(WPARAM wParam,LPARAM lParam)840 int	rvGEWorkspace::HandleMButtonUp ( WPARAM wParam, LPARAM lParam )
841 {
842 	if ( mDragScroll )
843 	{
844 		mDragScroll = false;
845 		ReleaseCapture ( );
846 	}
847 
848 	return 0;
849 }
850 
851 /*
852 ================
853 rvGEWorkspace::HandleRButtonDown
854 
855 Handles the left mouse down message in the workspace
856 ================
857 */
HandleRButtonDown(WPARAM wParam,LPARAM lParam)858 int	rvGEWorkspace::HandleRButtonDown ( WPARAM wParam, LPARAM lParam )
859 {
860 	POINT point = { LOWORD(lParam), HIWORD(lParam) };
861 	HMENU menu;
862 
863 	// Add the select menu
864 	mSelectMenu.Clear ( );
865 
866 	// Cache where the menu is being brought up so we can
867 	// figure out which windows are under the point
868 	mSelectMenuPos[0] = point.x;
869 	mSelectMenuPos[1] = point.y;
870 	WindowToWorkspace ( mSelectMenuPos );
871 
872 	// Build a list of all the windows under the menu point
873 	rvGEWindowWrapper::GetWrapper ( mInterface->GetDesktop() )->EnumChildren ( BuildSelectMenuEnumProc, this );
874 
875 	// Add the desktop window always
876 	mSelectMenu.Append ( mInterface->GetDesktop() );
877 
878 	//
879 	menu = GetSubMenu ( LoadMenu ( mApplication->GetInstance(), MAKEINTRESOURCE(IDR_GUIED_ITEM_POPUP) ), 0 );
880 
881 	HMENU popup = CreatePopupMenu ( );
882 
883 	int i;
884 	for ( i = 0; i < mSelectMenu.Num(); i ++ )
885 	{
886 		rvGEWindowWrapper* wrapper = rvGEWindowWrapper::GetWrapper ( mSelectMenu[i] );
887 		AppendMenu ( popup, MF_STRING|MF_ENABLED|(wrapper->IsSelected()?MF_CHECKED:0), ID_GUIED_SELECT_FIRST + i, mSelectMenu[i]->GetName() );
888 	}
889 
890 	InsertMenu ( menu, 1, MF_POPUP|MF_BYPOSITION, (LONG) popup, "Select" );
891 
892 	// Bring up the popup menu
893 	ClientToScreen ( mWnd, &point );
894 	TrackPopupMenu ( menu, TPM_RIGHTBUTTON|TPM_LEFTALIGN, point.x, point.y, 0, mWnd, NULL );
895 
896 	DestroyMenu ( popup );
897 	DestroyMenu ( menu );
898 
899 	return 0;
900 }
901 
902 /*
903 ================
904 rvGEWorkspace::HandleLButtonDown
905 
906 Handles the left mouse down message in the workspace
907 ================
908 */
HandleLButtonDown(WPARAM wParam,LPARAM lParam)909 int	rvGEWorkspace::HandleLButtonDown ( WPARAM wParam, LPARAM lParam )
910 {
911 	if ( mDragScroll )
912 	{
913 		return 0;
914 	}
915 
916 	idVec2 point ( LOWORD(lParam), HIWORD(lParam) );
917 	WindowToWorkspace ( point );
918 
919 	// Make sure whatever modifications get generated cant be merged into whats already there
920 	mModifiers.BlockNextMerge ( );
921 
922 	mDragPoint.Set ( LOWORD(lParam), HIWORD(lParam) );
923 	mDragTime = Sys_Milliseconds ( );
924 	mDragX    = true;
925 	mDragY    = true;
926 
927 	// If we have selections then start a drag
928 	if ( mSelections.Num ( ) )
929 	{
930 		mDragType = mSelections.HitTest ( mDragPoint.x, mDragPoint.y );
931 	}
932 
933 	rvGEWindowWrapper* wrapper;
934 	wrapper = rvGEWindowWrapper::GetWrapper ( mInterface->GetDesktop ( ) );
935 
936 	idWindow* window = wrapper->WindowFromPoint ( point.x, point.y );
937 
938 	// dissallow selection of the desktop.
939 	if ( gApp.GetOptions().GetIgnoreDesktopSelect() && window == mInterface->GetDesktop ( ) )
940 	{
941 		window = NULL;
942 	}
943 
944 	if ( mDragType == rvGESelectionMgr::HT_MOVE || mDragType == rvGESelectionMgr::HT_NONE )
945 	{
946 		if ( window  )
947 		{
948 			bool selected;
949 
950 			selected = mSelections.IsSelected ( window );
951 
952 			if ( GetAsyncKeyState ( VK_SHIFT ) & 0x8000 )
953 			{
954 				if ( !selected )
955 				{
956 					mSelections.Add ( window );
957 					mDragType = rvGESelectionMgr::HT_MOVE;
958 				}
959 				else
960 				{
961 					mSelections.Remove ( window );
962 				}
963 			}
964 			else if ( !selected && mDragType == rvGESelectionMgr::HT_NONE  )
965 			{
966 				mSelections.Set ( window );
967 				mDragType = rvGESelectionMgr::HT_MOVE;
968 			}
969 		}
970 		else
971 		{
972 			mSelections.Clear ( );
973 		}
974 	}
975 
976 	if ( mSelections.IsExpression ( ) )
977 	{
978 		mDragType = rvGESelectionMgr::HT_SELECT;
979 	}
980 	// Windows capture
981 	else if ( mDragType != rvGESelectionMgr::HT_NONE )
982 	{
983 		SetCapture ( mWnd );
984 	}
985 
986 	WindowToWorkspace ( mDragPoint );
987 
988 	return 0;
989 }
990 
991 /*
992 ================
993 rvGEWorkspace::HandleLButtonUp
994 
995 Handles the left mouse up message in the workspace
996 ================
997 */
HandleLButtonUp(WPARAM wParam,LPARAM lParam)998 int	rvGEWorkspace::HandleLButtonUp ( WPARAM wParam, LPARAM lParam )
999 {
1000 	if ( mDragType != rvGESelectionMgr::HT_NONE )
1001 	{
1002 		ReleaseCapture ( );
1003 		mModifiers.BlockNextMerge ( );
1004 
1005 		// Update the transformer
1006 		mApplication->GetTransformer().Update ( );
1007 	}
1008 
1009 	// No more dragging
1010 	mDragType = rvGESelectionMgr::HT_NONE;
1011 
1012 	return 0;
1013 }
1014 
1015 /*
1016 ================
1017 rvGEWorkspace::HandleLButtonDblClk
1018 
1019 Handle a double click by opening properties
1020 ================
1021 */
HandleLButtonDblClk(WPARAM wParam,LPARAM lParam)1022 int	rvGEWorkspace::HandleLButtonDblClk ( WPARAM wParam, LPARAM lParam )
1023 {
1024 	EditSelectedProperties ( );
1025 	return 0;
1026 }
1027 
1028 /*
1029 ================
1030 rvGEWorkspace::HandleMouseMove
1031 
1032 Handles the moving of the mouse for dragging and cursor updating
1033 ================
1034 */
HandleMouseMove(WPARAM wParam,LPARAM lParam)1035 int	rvGEWorkspace::HandleMouseMove ( WPARAM wParam, LPARAM lParam )
1036 {
1037 	idVec2	cursor;
1038 
1039 	cursor.Set ( (short)LOWORD(lParam), (short)HIWORD(lParam) );
1040 
1041 	// Convert the window point to the workspace before updating the
1042 	// cursor with the position
1043 	WindowToWorkspace ( cursor );
1044 
1045 	// Scrolling the window around
1046 	if ( mDragScroll )
1047 	{
1048 		Scroll ( SB_HORZ, mDragPoint.x - cursor.x );
1049 		Scroll ( SB_VERT, mDragPoint.y - cursor.y );
1050 
1051 		SetCursor ( mHandCursor );
1052 
1053 		mDragPoint = cursor;
1054 
1055 		return 0;
1056 	}
1057 
1058 	// If not dragging then just update the cursor and return
1059 	if ( mDragType == rvGESelectionMgr::HT_NONE )
1060 	{
1061 		UpdateCursor ( cursor.x, cursor.y );
1062 		return 0;
1063 	}
1064 
1065 	// Dont allow a drag move start until the button has been down for 100 ms or so
1066 	if ( mDragType == rvGESelectionMgr::HT_MOVE && Sys_Milliseconds() - mDragTime <= 50 )
1067 	{
1068 		return 0;
1069 	}
1070 
1071 	// Handle grid snapping
1072 	if ( gApp.GetOptions().GetGridSnap ( ) )
1073 	{
1074 		cursor.x = (float)(((int)cursor.x + gApp.GetOptions().GetGridWidth()/2) / gApp.GetOptions().GetGridWidth() * gApp.GetOptions().GetGridWidth());
1075 		cursor.y = (float)(((int)cursor.y + gApp.GetOptions().GetGridWidth()/2) / gApp.GetOptions().GetGridWidth() * gApp.GetOptions().GetGridWidth());
1076 	}
1077 
1078 	// If the cursor hasnt moved then there is nothing to update with the drag
1079 	if ( (int) cursor.x == (int) mDragPoint.x && (int) cursor.y == (int) mDragPoint.y )
1080 	{
1081 		return 0;
1082 	}
1083 
1084 	switch ( mDragType )
1085 	{
1086 		case rvGESelectionMgr::HT_MOVE:
1087 			AddModifierMove ( "Move", cursor.x - mDragPoint.x, cursor.y - mDragPoint.y, mApplication->GetOptions().GetGridSnap ( ) );
1088 			break;
1089 
1090 		case rvGESelectionMgr::HT_SIZE_BOTTOM:
1091 			AddModifierSize ( "Size", 0, 0, 0, cursor.y - mDragPoint.y, mApplication->GetOptions().GetGridSnap ( ) );
1092 			break;
1093 
1094 		case rvGESelectionMgr::HT_SIZE_TOP:
1095 			AddModifierSize ( "Size", 0, cursor.y - mDragPoint.y, 0, 0, mApplication->GetOptions().GetGridSnap ( ) );
1096 			break;
1097 
1098 		case rvGESelectionMgr::HT_SIZE_RIGHT:
1099 			AddModifierSize ( "Size", 0, 0, cursor.x - mDragPoint.x, 0, mApplication->GetOptions().GetGridSnap ( ) );
1100 			break;
1101 
1102 		case rvGESelectionMgr::HT_SIZE_LEFT:
1103 			AddModifierSize ( "Size", cursor.x - mDragPoint.x, 0, 0, 0, mApplication->GetOptions().GetGridSnap ( ) );
1104 			break;
1105 
1106 		case rvGESelectionMgr::HT_SIZE_TOPLEFT:
1107 			AddModifierSize ( "Size", cursor.x - mDragPoint.x, cursor.y - mDragPoint.y, 0, 0, mApplication->GetOptions().GetGridSnap ( ) );
1108 			break;
1109 
1110 		case rvGESelectionMgr::HT_SIZE_TOPRIGHT:
1111 			AddModifierSize ( "Size", 0, cursor.y - mDragPoint.y, cursor.x - mDragPoint.x, 0, mApplication->GetOptions().GetGridSnap ( ) );
1112 			break;
1113 
1114 		case rvGESelectionMgr::HT_SIZE_BOTTOMLEFT:
1115 			AddModifierSize ( "Size", cursor.x - mDragPoint.x, 0, 0, cursor.y - mDragPoint.y, mApplication->GetOptions().GetGridSnap ( ) );
1116 			break;
1117 
1118 		case rvGESelectionMgr::HT_SIZE_BOTTOMRIGHT:
1119 			AddModifierSize ( "Size", 0, 0, cursor.x - mDragPoint.x, cursor.y - mDragPoint.y, mApplication->GetOptions().GetGridSnap ( ) );
1120 			break;
1121 	}
1122 
1123 	UpdateCursor ( mDragType );
1124 
1125 	// If the x coordinate has changed then update it
1126 	if ( (int)cursor.x != (int)mDragPoint.x && mDragX )
1127 	{
1128 		mDragPoint.x = cursor.x;
1129 	}
1130 
1131 	// If the y coordinate has changed then update it
1132 	if ( (int)cursor.y != (int)mDragPoint.y && mDragY )
1133 	{
1134 		mDragPoint.y = cursor.y;
1135 	}
1136 
1137 	return 0;
1138 }
1139 
1140 /*
1141 ================
1142 rvGEWorkspace::HandleKeyDown
1143 
1144 Handles the the pressing of a key
1145 ================
1146 */
HandleKeyDown(WPARAM wParam,LPARAM lParam)1147 int	rvGEWorkspace::HandleKeyDown ( WPARAM wParam, LPARAM lParam )
1148 {
1149 	bool shift = (GetAsyncKeyState ( VK_SHIFT ) & 0x8000) ? true : false;
1150 
1151 	switch ( wParam )
1152 	{
1153 		case VK_LEFT:
1154 			if ( shift )
1155 			{
1156 				AddModifierSizeNudge ( -1, 0, false );
1157 			}
1158 			else
1159 			{
1160 				AddModifierMoveNudge ( -1, 0, false );
1161 			}
1162 			break;
1163 
1164 		case VK_RIGHT:
1165 			if ( shift )
1166 			{
1167 				AddModifierSizeNudge ( 1, 0, false );
1168 			}
1169 			else
1170 			{
1171 				AddModifierMoveNudge ( 1, 0, false );
1172 			}
1173 			break;
1174 
1175 		case VK_DOWN:
1176 			if ( shift )
1177 			{
1178 				AddModifierSizeNudge ( 0, 1, false );
1179 			}
1180 			else
1181 			{
1182 				AddModifierMoveNudge ( 0, 1, false );
1183 			}
1184 			break;
1185 
1186 		case VK_UP:
1187 			if ( shift )
1188 			{
1189 				AddModifierSizeNudge ( 0, -1, false );
1190 			}
1191 			else
1192 			{
1193 				AddModifierMoveNudge ( 0, -1, false );
1194 			}
1195 			break;
1196 
1197 		case VK_ESCAPE:
1198 			mSelections.Clear ( );
1199 			mApplication->GetNavigator().Update ( );
1200 			break;
1201 	}
1202 
1203 	return 0;
1204 }
1205 
1206 /*
1207 ================
1208 rvGEWorkspace::WindowToWorkspace
1209 
1210 Converts the given coordinates in windows space to the workspace's coordinates.
1211 ================
1212 */
WindowToWorkspace(idVec2 & point)1213 idVec2& rvGEWorkspace::WindowToWorkspace ( idVec2& point )
1214 {
1215 	point.x = (point.x - mRect.x) / mRect.w * SCREEN_WIDTH;
1216 	point.y = (point.y - mRect.y) / mRect.h * SCREEN_HEIGHT;
1217 
1218 	return point;
1219 }
1220 
WindowToWorkspace(idRectangle & rect)1221 idRectangle& rvGEWorkspace::WindowToWorkspace ( idRectangle& rect )
1222 {
1223 	rect.x = (rect.x - mRect.x) / mRect.w * SCREEN_WIDTH;
1224 	rect.y = (rect.y - mRect.y) / mRect.h * SCREEN_HEIGHT;
1225 	rect.w = rect.w / mRect.w * SCREEN_WIDTH;
1226 	rect.h = rect.h / mRect.h * SCREEN_HEIGHT;
1227 
1228 	return rect;
1229 }
1230 
1231 /*
1232 ================
1233 rvGEWorkspace::WindowToWorkspace
1234 
1235 Converts the given workspace coordinates to the windows coordinates.
1236 ================
1237 */
WorkspaceToWindow(idVec2 & point)1238 idVec2& rvGEWorkspace::WorkspaceToWindow ( idVec2& point )
1239 {
1240 	point.x = mRect.x + (point.x / SCREEN_WIDTH * mRect.w);
1241 	point.y = mRect.y + (point.y / SCREEN_HEIGHT * mRect.h);
1242 
1243 	return point;
1244 }
1245 
WorkspaceToWindow(idRectangle & rect)1246 idRectangle& rvGEWorkspace::WorkspaceToWindow ( idRectangle& rect )
1247 {
1248 	rect.x = mRect.x + (rect.x / SCREEN_WIDTH * mRect.w);
1249 	rect.y = mRect.y + (rect.y / SCREEN_HEIGHT * mRect.h);
1250 	rect.w = rect.w / SCREEN_WIDTH * mRect.w;
1251 	rect.h = rect.h / SCREEN_HEIGHT * mRect.h;
1252 
1253 	return rect;
1254 }
1255 
1256 /*
1257 ================
1258 rvGEWorkspace::ZoomIn
1259 
1260 Zooms the workspace in by one zoom level
1261 ================
1262 */
ZoomIn(void)1263 rvGEWorkspace::EZoomLevel rvGEWorkspace::ZoomIn ( void )
1264 {
1265 	mZoom = mZoom + 1;
1266 	if ( mZoom >= ZOOM_MAX )
1267 	{
1268 		mZoom = ZOOM_MAX - 1;
1269 	}
1270 
1271 	UpdateScrollbars ( );
1272 	UpdateTitle ( );
1273 
1274 	InvalidateRect ( mWnd, NULL, FALSE );
1275 
1276 	return (EZoomLevel)mZoom;
1277 }
1278 
1279 /*
1280 ================
1281 rvGEWorkspace::ZoomOut
1282 
1283 Zooms the workspace out by one level
1284 ================
1285 */
ZoomOut(void)1286 rvGEWorkspace::EZoomLevel rvGEWorkspace::ZoomOut ( void )
1287 {
1288 	mZoom--;
1289 	if ( mZoom <= ZOOM_MIN )
1290 	{
1291 		mZoom = ZOOM_MIN + 1;
1292 	}
1293 
1294 	UpdateScrollbars ( );
1295 	UpdateTitle ( );
1296 
1297 	InvalidateRect ( mWnd, NULL, FALSE );
1298 
1299 	return (EZoomLevel)mZoom;
1300 }
1301 
1302 /*
1303 ================
1304 rvGEWorkspace::CreateModifier
1305 
1306 Creates a new modifier of the given type for the given window.  This function is called
1307 specifically from the add modifiers function with the variable args list forwarded.
1308 ================
1309 */
CreateModifier(EModifierType type,idWindow * window,va_list args)1310 rvGEModifier* rvGEWorkspace::CreateModifier ( EModifierType type, idWindow* window, va_list args )
1311 {
1312 	rvGEModifier* mod;
1313 
1314 	switch ( type )
1315 	{
1316 		case MOD_DELETE:
1317 			mod = new rvGEDeleteModifier ( "Delete", window );
1318 			break;
1319 
1320 		case MOD_HIDE:
1321 			mod = new rvGEHideModifier ( "Hide", window, true );
1322 			break;
1323 
1324 		case MOD_UNHIDE:
1325 			mod = new rvGEHideModifier ( "Hide", window, false );
1326 			break;
1327 
1328 		case MOD_SEND_BACKWARD:
1329 			mod = new rvGEZOrderModifier ( "Send Backward", window, rvGEZOrderModifier::ZO_BACKWARD );
1330 			break;
1331 
1332 		case MOD_SEND_BACK:
1333 			mod = new rvGEZOrderModifier ( "Send to Back", window, rvGEZOrderModifier::ZO_BACK );
1334 			break;
1335 
1336 		case MOD_BRING_FORWARD:
1337 			mod = new rvGEZOrderModifier ( "Bring Forward", window, rvGEZOrderModifier::ZO_FORWARD );
1338 			break;
1339 
1340 		case MOD_BRING_FRONT:
1341 			mod = new rvGEZOrderModifier ( "Bring to Front", window, rvGEZOrderModifier::ZO_FRONT );
1342 			break;
1343 
1344 		default:
1345 			mod = NULL;
1346 			break;
1347 	}
1348 
1349 	return mod;
1350 }
1351 
1352 /*
1353 ================
1354 rvGEWorkspace::AddModifiers
1355 
1356 Add the specific modifier for the given window
1357 ================
1358 */
AddModifiers(idWindow * window,EModifierType type,...)1359 void rvGEWorkspace::AddModifiers ( idWindow* window, EModifierType type, ... )
1360 {
1361 	va_list args;
1362 
1363 	va_start(args,type) ;
1364 	mModifiers.Append ( CreateModifier ( type, window, args ) );
1365 	va_end (args) ;
1366 
1367 	SetModified ( true );
1368 }
1369 
AddModifiers(EModifierType type,...)1370 void rvGEWorkspace::AddModifiers ( EModifierType type, ... )
1371 {
1372 	va_list args;
1373 
1374 	// Nothing to move if there is no selection
1375 	if ( !mSelections.Num ( ) )
1376 	{
1377 		return;
1378 	}
1379 	// More than one selection requires a modifier group
1380 	else if ( mSelections.Num ( ) > 1 )
1381 	{
1382 		rvGEModifierGroup*	group = new rvGEModifierGroup;
1383 		int					i;
1384 
1385 		for ( i = 0; i < mSelections.Num(); i ++ )
1386 		{
1387 			va_start(args,type);
1388 			group->Append ( CreateModifier ( type, mSelections[i], args ) );
1389 			va_end (args);
1390 		}
1391 
1392 		mModifiers.Append ( group );
1393 	}
1394 	// Single modifier
1395 	else
1396 	{
1397 		va_start(args,type) ;
1398 		mModifiers.Append ( CreateModifier ( type, mSelections[0], args ) );
1399 		va_end (args) ;
1400 	}
1401 
1402 	SetModified ( true );
1403 }
1404 
BuildSelectMenuEnumProc(rvGEWindowWrapper * wrapper,void * data)1405 bool rvGEWorkspace::BuildSelectMenuEnumProc ( rvGEWindowWrapper* wrapper, void* data )
1406 {
1407 	rvGEWorkspace*	workspace;
1408 
1409 	workspace = (rvGEWorkspace*) data;
1410 	assert ( workspace );
1411 
1412 	if ( !wrapper )
1413 	{
1414 		return true;
1415 	}
1416 
1417 	wrapper->EnumChildren ( BuildSelectMenuEnumProc, data );
1418 
1419 	if ( wrapper->IsDeleted ( ) || wrapper->IsHidden ( ) )
1420 	{
1421 		return true;
1422 	}
1423 
1424 	if ( wrapper->GetScreenRect ( ).Contains ( workspace->mSelectMenuPos[0], workspace->mSelectMenuPos[1] ) )
1425 	{
1426 		workspace->mSelectMenu.Append ( wrapper->GetWindow ( ));
1427 	}
1428 
1429 	return true;
1430 }
1431 
ShowAllEnumProc(rvGEWindowWrapper * wrapper,void * data)1432 bool rvGEWorkspace::ShowAllEnumProc ( rvGEWindowWrapper* wrapper, void* data )
1433 {
1434 	rvGEModifierGroup* group = (rvGEModifierGroup*) data;
1435 
1436 	wrapper->EnumChildren ( ShowAllEnumProc, data );
1437 
1438 	if ( wrapper->IsHidden ( ) )
1439 	{
1440 		group->Append ( new rvGEHideModifier ( "Show Hidden", wrapper->GetWindow ( ), false ) );
1441 	}
1442 
1443 	return true;
1444 }
1445 
AddModifierShowAll(void)1446 void rvGEWorkspace::AddModifierShowAll ( void )
1447 {
1448 	rvGEModifierGroup* group = new rvGEModifierGroup;
1449 
1450 	rvGEWindowWrapper::GetWrapper( mInterface->GetDesktop ( ) )->EnumChildren ( ShowAllEnumProc, group );
1451 
1452 	if ( !group->GetCount ( ) )
1453 	{
1454 		delete group;
1455 	}
1456 	else
1457 	{
1458 		mModifiers.Append ( group );
1459 	}
1460 
1461 	mApplication->GetNavigator().Refresh ( );
1462 }
1463 
DeleteSelected(void)1464 void rvGEWorkspace::DeleteSelected ( void )
1465 {
1466 	AddModifiers ( MOD_DELETE );
1467 	mSelections.Clear ( );
1468 	mApplication->GetNavigator().Update ( );
1469 }
1470 
1471 /*
1472 ================
1473 rvGEWorkspace::NewWindow
1474 
1475 Create a new window
1476 ================
1477 */
NewWindow(idDict * state,rvGEWindowWrapper::EWindowType type)1478 idWindow* rvGEWorkspace::NewWindow ( idDict* state, rvGEWindowWrapper::EWindowType type )
1479 {
1480 	idWindow*			window = new idWindow ( mInterface->GetDesktop()->GetDC(), mInterface );
1481 	rvGEWindowWrapper*	wrapper;
1482 	int					count;
1483 	idStr				baseName;
1484 
1485 	switch ( type )
1486 	{
1487 		case rvGEWindowWrapper::WT_NORMAL:
1488 			window = new idWindow ( mInterface->GetDesktop()->GetDC(), mInterface );
1489 			break;
1490 
1491 		case rvGEWindowWrapper::WT_BIND:
1492 			window = new idBindWindow ( mInterface->GetDesktop()->GetDC(), mInterface );
1493 			break;
1494 
1495 		case rvGEWindowWrapper::WT_RENDER:
1496 			window = new idRenderWindow ( mInterface->GetDesktop()->GetDC(), mInterface );
1497 			break;
1498 
1499 		case rvGEWindowWrapper::WT_CHOICE:
1500 			window = new idChoiceWindow ( mInterface->GetDesktop()->GetDC(), mInterface );
1501 			break;
1502 
1503 		case rvGEWindowWrapper::WT_EDIT:
1504 			window = new idEditWindow ( mInterface->GetDesktop()->GetDC(), mInterface );
1505 			break;
1506 
1507 		default:
1508 			assert ( false );
1509 			return NULL;
1510 	}
1511 
1512 	baseName = state ? state->GetString("name","unnamed") : "unnamed";
1513 	baseName.StripQuotes ( );
1514 
1515 	count = 0;
1516 	if ( mInterface->GetDesktop()->FindChildByName ( baseName ) )
1517 	{
1518 		count = 1;
1519 		while ( 1 )
1520 		{
1521 			drawWin_t* dw = mInterface->GetDesktop()->FindChildByName ( va("%s%d",baseName.c_str(),count) );
1522 			if ( !dw )
1523 			{
1524 				break;
1525 			}
1526 			assert ( dw->win );
1527 			wrapper = rvGEWindowWrapper::GetWrapper ( dw->win );
1528 			if ( wrapper && wrapper->IsDeleted ( ) )
1529 			{
1530 				break;
1531 			}
1532 			count++;
1533 		}
1534 	}
1535 
1536 	idStr winName;
1537 	idStr winTemplate;
1538 
1539 	if ( count )
1540 	{
1541 		winName = va("%s%d", baseName.c_str(), count );
1542 	}
1543 	else
1544 	{
1545 		winName = baseName;
1546 	}
1547 	winTemplate = winName + " { }";
1548 
1549 	idParser src( winTemplate, winTemplate.Length(), "", LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
1550 	window->Parse ( &src );
1551 
1552 	wrapper = rvGEWindowWrapper::GetWrapper ( window );
1553 
1554 	if ( state )
1555 	{
1556 		wrapper->SetState ( *state );
1557 	}
1558 
1559 	wrapper->SetStateKey ( "name", winName );
1560 	wrapper->Finish ( );
1561 
1562 	SetModified ( true );
1563 
1564 
1565 	return window;
1566 }
1567 
AddWindow(rvGEWindowWrapper::EWindowType type)1568 idWindow* rvGEWorkspace::AddWindow ( rvGEWindowWrapper::EWindowType type )
1569 {
1570 	idWindow*	window;
1571 	idDict		state;
1572 
1573 	state.Set ( "rect", "0,0,100,100" );
1574 	state.Set ( "visible", "1" );
1575 
1576 	window = NewWindow ( &state, type );
1577 	assert ( window );
1578 
1579 	mModifiers.Append ( new rvGEInsertModifier ( "New", window, mInterface->GetDesktop(), NULL ) );
1580 
1581 	mSelections.Set ( window );
1582 	mApplication->GetNavigator().Update ( );
1583 	mApplication->GetTransformer().Update ( );
1584 	mApplication->GetProperties().Update ( );
1585 
1586 	return window;
1587 }
1588 
EditSelectedProperties(void)1589 bool rvGEWorkspace::EditSelectedProperties ( void )
1590 {
1591 	if ( !mSelections.Num ( ) || mSelections.Num() > 1 )
1592 	{
1593 		return false;
1594 	}
1595 
1596 	idDict dict;
1597 	if ( GEItemPropsDlg_DoModal ( mWnd, mSelections[0], dict ) )
1598 	{
1599 		mModifiers.Append ( new rvGEStateModifier ( "Item Properties", mSelections[0], dict ) );
1600 		SetModified ( true );
1601 	}
1602 
1603 	mApplication->GetNavigator().Update ( );
1604 	mApplication->GetTransformer().Update ( );
1605 	mApplication->GetProperties().Update ( );
1606 
1607 	return true;
1608 }
1609 
EditSelectedScripts(void)1610 bool rvGEWorkspace::EditSelectedScripts ( void )
1611 {
1612 	if ( GEItemScriptsDlg_DoModal ( mWnd, mSelections[0] ) )
1613 	{
1614 		gApp.GetNavigator().Refresh ( );
1615 		SetModified ( true );
1616 	}
1617 
1618 	return true;
1619 }
1620 
BringSelectedForward(void)1621 void rvGEWorkspace::BringSelectedForward ( void )
1622 {
1623 	AddModifiers ( MOD_BRING_FORWARD );
1624 	mApplication->GetNavigator().Update ( );
1625 }
1626 
BringSelectedToFront(void)1627 void rvGEWorkspace::BringSelectedToFront ( void )
1628 {
1629 	AddModifiers ( MOD_BRING_FRONT );
1630 	mApplication->GetNavigator().Update ( );
1631 }
1632 
SendSelectedToBack(void)1633 void rvGEWorkspace::SendSelectedToBack ( void )
1634 {
1635 	AddModifiers ( MOD_SEND_BACK );
1636 	mApplication->GetNavigator().Update ( );
1637 }
1638 
SendSelectedBackward(void)1639 void rvGEWorkspace::SendSelectedBackward ( void )
1640 {
1641 	AddModifiers ( MOD_SEND_BACKWARD );
1642 	mApplication->GetNavigator().Update ( );
1643 }
1644 
1645 /*
1646 ================
1647 rvGEWorkspace::MakeSelectedSameSize
1648 
1649 Align the selected items to the first one using the given align type
1650 ================
1651 */
MakeSelectedSameSize(bool changeWidth,bool changeHeight)1652 void rvGEWorkspace::MakeSelectedSameSize ( bool changeWidth, bool changeHeight )
1653 {
1654 	rvGEModifierGroup*	group;
1655 	idRectangle			rectTo;
1656 	int					i;
1657 
1658 	group = new rvGEModifierGroup ( );
1659 
1660 	rectTo = rvGEWindowWrapper::GetWrapper ( mSelections[0] )->GetClientRect ( );
1661 
1662 	for ( i = 1; i < mSelections.Num(); i ++ )
1663 	{
1664 		idRectangle	rectFrom;
1665 		float		width = 0;
1666 		float		height = 0;
1667 
1668 		rectFrom = rvGEWindowWrapper::GetWrapper(mSelections[i])->GetClientRect ();
1669 
1670 		if ( changeWidth )
1671 		{
1672 			width = rectTo.w - rectFrom.w;
1673 		}
1674 
1675 		if ( changeHeight )
1676 		{
1677 			height = rectTo.h - rectFrom.h;
1678 		}
1679 
1680 		group->Append ( new rvGESizeModifier ( "Make Same Size", mSelections[i], 0, 0, width, height ) );
1681 	}
1682 
1683 	mModifiers.Append ( group );
1684 
1685 	// Cant merge alignments
1686 	mModifiers.BlockNextMerge ( );
1687 
1688 	SetModified ( true );
1689 }
1690 
1691 /*
1692 ================
1693 rvGEWorkspace::AlignSelected
1694 
1695 Align the selected items to the first one using the given align type
1696 ================
1697 */
AlignSelected(EItemAlign align)1698 void rvGEWorkspace::AlignSelected ( EItemAlign align )
1699 {
1700 	static const char*	alignNames[]={"Lefts","Centers","Rights","Tops","Middles","Bottoms" };
1701 	int					i;
1702 	idStr				modName;
1703 	rvGEModifierGroup*	group;
1704 
1705 	assert ( mSelections.Num() > 1 );
1706 
1707 	modName = "Align " + idStr(alignNames[align]);
1708 
1709 	group   = new rvGEModifierGroup ( );
1710 
1711 	idRectangle rectTo;
1712 	rectTo = rvGEWindowWrapper::GetWrapper ( mSelections[0] )->GetScreenRect ( );
1713 
1714 	// Everything gets aligned to the first selection so run
1715 	// through all other selections and move them.
1716 	for ( i = 1; i < mSelections.Num(); i ++ )
1717 	{
1718 		float		x;
1719 		float		y;
1720 		idRectangle	rectFrom;
1721 
1722 		rectFrom = rvGEWindowWrapper::GetWrapper ( mSelections[i] )->GetScreenRect ( );
1723 
1724 		switch ( align )
1725 		{
1726 			case ALIGN_LEFTS:
1727 				x = rectTo[0] - rectFrom[0];
1728 				y = 0;
1729 				break;
1730 
1731 			case ALIGN_RIGHTS:
1732 				x = (rectTo[0]+rectTo[2]) - (rectFrom[0]+rectFrom[2]);
1733 				y = 0;
1734 				break;
1735 
1736 			case ALIGN_CENTERS:
1737 				x = (rectTo[0]+rectTo[2]/2) - (rectFrom[0]+rectFrom[2]/2);
1738 				y = 0;
1739 				break;
1740 
1741 			case ALIGN_TOPS:
1742 				y = rectTo[1] - rectFrom[1];
1743 				x = 0;
1744 				break;
1745 
1746 			case ALIGN_BOTTOMS:
1747 				x = 0;
1748 				y = (rectTo[1]+rectTo[3]) - (rectFrom[1]+rectFrom[3]);
1749 				break;
1750 
1751 			case ALIGN_MIDDLES:
1752 				x = 0;
1753 				y = (rectTo[1]+rectTo[3]/2) - (rectFrom[1]+rectFrom[3]/2);
1754 				break;
1755 
1756 			default:
1757 				assert ( false );
1758 				break;
1759 		}
1760 
1761 		group->Append ( new rvGEMoveModifier ( modName, mSelections[i], x, y ) );
1762 	}
1763 
1764 	mModifiers.Append ( group );
1765 
1766 	// Cant merge alignments
1767 	mModifiers.BlockNextMerge ( );
1768 
1769 	SetModified ( true );
1770 }
1771 
1772 /*
1773 ================
1774 rvGEWorkspace::AddModifierMove
1775 
1776 Adds a move modifier with the given offsets
1777 ================
1778 */
AddModifierMove(const char * modName,float x,float y,bool snap)1779 void rvGEWorkspace::AddModifierMove ( const char* modName, float x, float y, bool snap )
1780 {
1781 	idRectangle scaleRect;
1782 	idRectangle newRect;
1783 
1784 	scaleRect = mSelections.GetRect ( );
1785 	WindowToWorkspace ( scaleRect );
1786 	newRect   = scaleRect;
1787 	newRect.x += x;
1788 	newRect.y += y;
1789 
1790 	if ( snap )
1791 	{
1792 		gApp.GetOptions ().SnapRectToGrid ( newRect, true, true, false, false );
1793 	}
1794 
1795 	rvGEModifierGroup*	group = new rvGEModifierGroup;
1796 	for ( int i = 0; i < mSelections.Num(); i ++ )
1797 	{
1798 		if ( !mSelections[i]->GetParent ( ) )
1799 		{
1800 			continue;
1801 		}
1802 
1803 		// IF the parent window is being moved around as well then dont move this one.
1804 		if ( rvGEWindowWrapper::GetWrapper ( mSelections[i]->GetParent ( ) )->IsSelected ( ) )
1805 		{
1806 			// We still need the modifier there so the selection can be restored and
1807 			// so the rectangle gets updated
1808 			group->Append ( new rvGEMoveModifier ( modName, mSelections[i], 0, 0 ) );
1809 			continue;
1810 		}
1811 
1812 		group->Append ( new rvGEMoveModifier ( modName, mSelections[i], newRect.x-scaleRect.x, newRect.y-scaleRect.y ) );
1813 	}
1814 
1815 	mModifiers.Append ( group );
1816 
1817 	SetModified ( true );
1818 }
1819 
1820 /*
1821 ================
1822 rvGEWorkspace::AddModifierSize
1823 
1824 Adds a size modifier with the given offsets
1825 ================
1826 */
AddModifierSize(const char * modName,float l,float t,float r,float b,bool snap)1827 void rvGEWorkspace::AddModifierSize ( const char* modName, float l, float t, float r, float b, bool snap )
1828 {
1829 	idRectangle scaleRect;
1830 	idRectangle	sizeRect;
1831 	idRectangle newRect;
1832 
1833 	scaleRect = mSelections.GetRect ( );
1834 	WindowToWorkspace ( scaleRect );
1835 	newRect = scaleRect;
1836 	newRect.x += l;
1837 	newRect.y += t;
1838 	newRect.w += (r - l);
1839 	newRect.h += (b - t);
1840 
1841 	// Restrict sizing below 1 width
1842 	if ( newRect.w <= 1 )
1843 	{
1844 		newRect.x	 = newRect.x - (l ? (1 - newRect.w) : 0);
1845 		mDragPoint.x = newRect.x;
1846 		newRect.w	 = 1;
1847 		mDragX		 = false;
1848 	}
1849 	else
1850 	{
1851 		mDragX = true;
1852 	}
1853 
1854 	// Restrict sizing below 1 height
1855 	if ( newRect.h <= 1 )
1856 	{
1857 		newRect.y	 = newRect.y - (t ? (1 - newRect.h) : 0);
1858 		mDragPoint.y = newRect.y;
1859 		newRect.h	 = 1;
1860 		mDragY		 = false;
1861 	}
1862 	else
1863 	{
1864 		mDragY = true;
1865 	}
1866 
1867 	if ( snap )
1868 	{
1869 		gApp.GetOptions ().SnapRectToGrid ( newRect, l != 0.0f, t != 0.0f, r != 0.0f, b != 0.0f );
1870 	}
1871 
1872 	rvGEModifierGroup*	group = new rvGEModifierGroup;
1873 	for ( int i = 0; i < mSelections.Num(); i ++ )
1874 	{
1875 		sizeRect  = rvGEWindowWrapper::GetWrapper ( mSelections[i] )->GetScreenRect ( );
1876 
1877 		l = (newRect.x + ((sizeRect.x - scaleRect.x) / scaleRect.w) * newRect.w) - sizeRect.x;
1878 		t = (newRect.y + ((sizeRect.y - scaleRect.y) / scaleRect.h) * newRect.h) - sizeRect.y;
1879 		r = (sizeRect.w / scaleRect.w * newRect.w) - sizeRect.w + l;
1880 		b = (sizeRect.h / scaleRect.h * newRect.h) - sizeRect.h + t;
1881 
1882 		// This is sorta crufty but needs to be done.  When a parent is being sized at the same
1883 		// time as a child you will get double movement because the child is relative to the parent.  Therefore
1884 		// we need to subtract out the closest parents sizing.
1885 		idWindow* parent = mSelections[i];
1886 		while ( NULL != (parent = parent->GetParent ( ) ) )
1887 		{
1888 			rvGEWindowWrapper*	pwrapper = rvGEWindowWrapper::GetWrapper ( parent );
1889 			float				offset;
1890 
1891 			if ( !pwrapper->IsSelected ( ) )
1892 			{
1893 				continue;
1894 			}
1895 
1896 			sizeRect  = pwrapper->GetScreenRect ( );
1897 
1898 			// Subtract out the left and right modifications
1899 			offset = ((newRect.x + ((sizeRect.x - scaleRect.x) / scaleRect.w) * newRect.w) - sizeRect.x);
1900 			l -= offset;
1901 			r -= offset;
1902 
1903 			// Subtract out the top and bottom modifications
1904 			offset = ((newRect.y + ((sizeRect.y - scaleRect.y) / scaleRect.h) * newRect.h) - sizeRect.y);
1905 			t -= offset;
1906 			b -= offset;
1907 
1908 			break;
1909 		}
1910 
1911 		group->Append ( new rvGESizeModifier ( modName, mSelections[i], l, t, r, b ) );
1912 	}
1913 
1914 	mModifiers.Append ( group );
1915 
1916 	SetModified ( true );
1917 }
1918 
1919 /*
1920 ================
1921 rvGEWorkspace::MakeSelectedAChild
1922 
1923 Makes the selected windows a child of the first selected window
1924 ================
1925 */
MakeSelectedAChild(void)1926 void rvGEWorkspace::MakeSelectedAChild ( void )
1927 {
1928 	rvGEModifierGroup*	group;
1929 	int					i;
1930 
1931 	if ( !rvGEWindowWrapper::GetWrapper ( mSelections[0] )->CanHaveChildren ( ) )
1932 	{
1933 		gApp.MessageBox ( "Cannot add children to an htmlDef item", MB_OK|MB_ICONERROR );
1934 		return;
1935 	}
1936 
1937 	group = new rvGEModifierGroup;
1938 
1939 	for ( i = 1; i < mSelections.Num(); i ++ )
1940 	{
1941 		if ( mSelections[i]->GetParent ( ) == mSelections[0] )
1942 		{
1943 			continue;
1944 		}
1945 
1946 		if ( !mSelections[i]->GetParent ( ) )
1947 		{
1948 			continue;
1949 		}
1950 
1951 		group->Append ( new rvGEInsertModifier ( "Make Child", mSelections[i], mSelections[0], NULL ) );
1952 	}
1953 
1954 	mModifiers.Append ( group );
1955 
1956 	// Navigator needs an update since the ordering has changed
1957 	gApp.GetNavigator().Update ( );
1958 
1959 	SetModified ( true );
1960 }
1961 
Copy(void)1962 void rvGEWorkspace::Copy ( void )
1963 {
1964 	int i;
1965 
1966 	// Clear the current clipboard
1967 	for ( i = 0; i < mClipboard.Num(); i ++ )
1968 	{
1969 		delete mClipboard[i];
1970 	}
1971 
1972 	mClipboard.Clear ( );
1973 
1974 	for ( i = 0; i < mSelections.Num(); i ++ )
1975 	{
1976 		rvGEWindowWrapper* wrapper = rvGEWindowWrapper::GetWrapper ( mSelections[i] );
1977 		assert ( wrapper );
1978 
1979 		rvGEClipboardItem* item = new rvGEClipboardItem;
1980 		item->mStateDict  = wrapper->GetStateDict ( );
1981 		item->mScriptDict = wrapper->GetScriptDict ( );
1982 		item->mVarDict    = wrapper->GetVariableDict ( );
1983 
1984 		item->mStateDict.Set ( "windowType", rvGEWindowWrapper::WindowTypeToString ( wrapper->GetWindowType ( ) ) );
1985 
1986 		mClipboard.Append ( item );
1987 	}
1988 }
1989 
Paste(void)1990 void rvGEWorkspace::Paste ( void )
1991 {
1992 	int i;
1993 
1994 	rvGEModifierGroup* group = new rvGEModifierGroup;
1995 
1996 	mSelections.Clear ( );
1997 
1998 	for ( i = 0; i < mClipboard.Num(); i ++ )
1999 	{
2000 		idDict							state;
2001 		rvGEWindowWrapper::EWindowType	type;
2002 
2003 		state.Copy ( mClipboard[i]->mStateDict );
2004 		type = rvGEWindowWrapper::StringToWindowType ( state.GetString ( "windowType", "windowDef" ) );
2005 		state.Delete ( "windowType" );
2006 
2007 		idWindow* window = NewWindow ( &state, type );
2008 		group->Append ( new rvGEInsertModifier ( "Paste", window, mInterface->GetDesktop(), NULL ) );
2009 		mSelections.Add ( window );
2010 
2011 		rvGEWindowWrapper::GetWrapper ( window )->GetScriptDict ( ) = mClipboard[i]->mScriptDict;
2012 		rvGEWindowWrapper::GetWrapper ( window )->GetVariableDict ( ) = mClipboard[i]->mVarDict;
2013 	}
2014 
2015 	mModifiers.Append ( group );
2016 
2017 	mApplication->GetNavigator().Update ( );
2018 
2019 	SetModified ( true );
2020 }
2021 
HideSelected(void)2022 void rvGEWorkspace::HideSelected ( void )
2023 {
2024 	AddModifiers ( MOD_HIDE );
2025 	mSelections.Clear ( );
2026 	mApplication->GetNavigator().Refresh ( );
2027 }
2028 
UnhideSelected(void)2029 void rvGEWorkspace::UnhideSelected ( void )
2030 {
2031 	AddModifiers ( MOD_UNHIDE );
2032 	mApplication->GetNavigator().Refresh ( );
2033 }
2034 
HideWindow(idWindow * window)2035 void rvGEWorkspace::HideWindow ( idWindow* window )
2036 {
2037 	AddModifiers ( window, MOD_HIDE );
2038 	mApplication->GetNavigator().Refresh ( );
2039 }
2040 
UnhideWindow(idWindow * window)2041 void rvGEWorkspace::UnhideWindow ( idWindow* window )
2042 {
2043 	AddModifiers ( window, MOD_UNHIDE );
2044 	mApplication->GetNavigator().Refresh ( );
2045 }
2046 
2047 /*
2048 ================
2049 rvGEWorkspace::SetModified
2050 
2051 Sets the modified state of the window and if source control is enabled it
2052 will attempt to check out the file
2053 ================
2054 */
SetModified(bool mod)2055 void rvGEWorkspace::SetModified ( bool mod )
2056 {
2057 	if ( mModified != mod )
2058 	{
2059 
2060 		mModified = mod;
2061 		UpdateTitle ( );
2062 
2063 	}
2064 }
2065