Script editor now is in a seperate tab

This commit is contained in:
Justin Marshall
2026-05-18 12:58:13 -07:00
parent 1c1f828271
commit 222cccc1f0
8 changed files with 5176 additions and 646 deletions
+190 -47
View File
@@ -56,15 +56,46 @@ const int FUNCPARMTOOLTIP_WIDTH = 16;
const int FUNCPARMTOOLTIP_HEIGHT = 20;
const int FUNCPARMTOOLTIP_OFFSET = 16;
const COLORREF DEFAULT_BACK_COLOR = SRE_COLOR_WHITE;
const COLORREF INVALID_BACK_COLOR = SRE_COLOR_WHITE - 2;
const COLORREF MULTILINE_COMMENT_BACK_COLOR = SRE_COLOR_WHITE - 1;
// Dark theme colors used by the docked script editor. These are kept in the
// syntax control instead of only in DialogScriptEditor because TOM restores
// m_DefaultFont during HighlightSyntax(), so a white default font/background
// here will repaint the editor white even after EM_SETBKGNDCOLOR was applied.
const COLORREF SRE_DARK_DEFAULT_TEXT = RGB( 226, 232, 240 );
const COLORREF SRE_DARK_DEFAULT_BACK = RGB( 11, 13, 18 );
const COLORREF SRE_DARK_INVALID_BACK = RGB( 17, 24, 39 );
const COLORREF SRE_DARK_MULTILINE_COMMENT_BACK = RGB( 13, 24, 18 );
const COLORREF SRE_DARK_COMMENT = RGB( 106, 153, 85 );
const COLORREF SRE_DARK_STRING = RGB( 214, 157, 133 );
const COLORREF SRE_DARK_STRING_ALT = RGB( 220, 180, 130 );
const COLORREF SRE_DARK_LITERAL = RGB( 181, 206, 168 );
const COLORREF SRE_DARK_BRACE = RGB( 255, 203, 107 );
const COLORREF DEFAULT_BACK_COLOR = SRE_DARK_DEFAULT_BACK;
const COLORREF INVALID_BACK_COLOR = SRE_DARK_INVALID_BACK;
const COLORREF MULTILINE_COMMENT_BACK_COLOR = SRE_DARK_MULTILINE_COMMENT_BACK;
static COLORREF SREMakeReadableOnDark( COLORREF color ) {
int r = GetRValue( color );
int g = GetGValue( color );
int b = GetBValue( color );
int luma = ( r * 299 + g * 587 + b * 114 ) / 1000;
// Old .def files were authored for a white editor and often use black or
// very dark colors. Blend those toward a readable foreground for the dark UI.
if ( luma < 90 ) {
r = ( r + 120 > 255 ) ? 255 : r + 120;
g = ( g + 120 > 255 ) ? 255 : g + 120;
b = ( b + 120 > 255 ) ? 255 : b + 120;
}
return RGB( r, g, b );
}
#define IDC_LISTBOX_AUTOCOMPLETE 700
#define IDC_EDITBOX_FUNCPARMS 701
static keyWord_t defaultKeyWords[] = {
{ NULL, SRE_COLOR_BLACK, "" }
{ NULL, SRE_DARK_DEFAULT_TEXT, "" }
};
BEGIN_MESSAGE_MAP(CSyntaxRichEditCtrl, CRichEditCtrl)
@@ -93,6 +124,7 @@ CSyntaxRichEditCtrl::CSyntaxRichEditCtrl
*/
CSyntaxRichEditCtrl::CSyntaxRichEditCtrl( void ) {
m_TextDoc = NULL;
m_DefaultFont = NULL;
keyWords = defaultKeyWords;
keyWordColors = NULL;
keyWordLengths = NULL;
@@ -125,9 +157,18 @@ CSyntaxRichEditCtrl::~CSyntaxRichEditCtrl
*/
CSyntaxRichEditCtrl::~CSyntaxRichEditCtrl( void ) {
FreeKeyWordsFromFile();
delete m_pchTip;
delete m_pwchTip;
m_DefaultFont->Release();
delete [] m_pchTip;
delete [] m_pwchTip;
if ( m_DefaultFont != NULL ) {
m_DefaultFont->Release();
m_DefaultFont = NULL;
}
if ( m_TextDoc != NULL ) {
m_TextDoc->Release();
m_TextDoc = NULL;
}
}
/*
@@ -136,6 +177,10 @@ CSyntaxRichEditCtrl::InitFont
================
*/
void CSyntaxRichEditCtrl::InitFont( void ) {
if ( m_TextDoc == NULL || GetSafeHwnd() == NULL ) {
return;
}
LOGFONT lf;
CFont font;
PARAFORMAT pf;
@@ -171,27 +216,39 @@ void CSyntaxRichEditCtrl::InitFont( void ) {
defaultCharFormat.yHeight = FONT_HEIGHT * 20;
defaultCharFormat.bCharSet = ANSI_CHARSET;
defaultCharFormat.bPitchAndFamily = FIXED_PITCH | FF_MODERN;
defaultCharFormat.crTextColor = SRE_COLOR_BLACK;
defaultCharFormat.crTextColor = SRE_DARK_DEFAULT_TEXT;
defaultCharFormat.crBackColor = DEFAULT_BACK_COLOR;
defaultCharFormat.dwEffects = CFE_PROTECTED;
strcpy( defaultCharFormat.szFaceName, FONT_NAME );
defaultCharFormat.cbSize = sizeof( defaultCharFormat );
SetDefaultCharFormat( defaultCharFormat );
SendMessage( EM_SETBKGNDCOLOR, 0, DEFAULT_BACK_COLOR );
defaultColor = SRE_COLOR_BLACK;
singleLineCommentColor = SRE_COLOR_DARK_GREEN;
multiLineCommentColor = SRE_COLOR_DARK_GREEN;
stringColor[0] = stringColor[1] = SRE_COLOR_DARK_CYAN;
literalColor = SRE_COLOR_GREY;
braceHighlightColor = SRE_COLOR_RED;
defaultColor = SRE_DARK_DEFAULT_TEXT;
singleLineCommentColor = SRE_DARK_COMMENT;
multiLineCommentColor = SRE_DARK_COMMENT;
stringColor[0] = SRE_DARK_STRING;
stringColor[1] = SRE_DARK_STRING_ALT;
literalColor = SRE_DARK_LITERAL;
braceHighlightColor = SRE_DARK_BRACE;
// get the default tom::ITextFont
tom::ITextRange *irange;
tom::ITextFont *ifont;
tom::ITextRange *irange = NULL;
tom::ITextFont *ifont = NULL;
m_TextDoc->Range( 0, 0, &irange );
irange->get_Font( &ifont );
if ( m_DefaultFont != NULL ) {
m_DefaultFont->Release();
m_DefaultFont = NULL;
}
if ( m_TextDoc->Range( 0, 0, &irange ) != S_OK || irange == NULL ) {
return;
}
if ( irange->get_Font( &ifont ) != S_OK || ifont == NULL ) {
irange->Release();
return;
}
ifont->get_Duplicate( &m_DefaultFont );
@@ -235,14 +292,24 @@ CSyntaxRichEditCtrl::Init
*/
void CSyntaxRichEditCtrl::Init( void ) {
// get the Rich Edit ITextDocument to use the wonky TOM interface
IRichEditOle *ire = GetIRichEditOle();
IUnknown *iu = (IUnknown *)ire;
if ( iu == NULL || iu->QueryInterface( tom::IID_ITextDocument, (void**) &m_TextDoc ) != S_OK ) {
m_TextDoc = NULL;
if ( GetSafeHwnd() == NULL ) {
return;
}
InitFont();
// get the Rich Edit ITextDocument to use the wonky TOM interface
// WM_SIZE can arrive during CRichEditCtrl::Create before Init() runs, so
// every TOM-dependent path must tolerate m_TextDoc == NULL until this succeeds.
if ( m_TextDoc == NULL ) {
IRichEditOle *ire = GetIRichEditOle();
IUnknown *iu = (IUnknown *)ire;
if ( iu == NULL || iu->QueryInterface( tom::IID_ITextDocument, (void**) &m_TextDoc ) != S_OK ) {
m_TextDoc = NULL;
}
}
if ( m_TextDoc != NULL && m_DefaultFont == NULL ) {
InitFont();
}
InitSyntaxHighlighting();
@@ -252,14 +319,18 @@ void CSyntaxRichEditCtrl::Init( void ) {
// create auto complete list box
CRect rect( 0, 0, AUTOCOMPLETE_WIDTH, AUTOCOMPLETE_HEIGHT );
autoCompleteListBox.Create( WS_DLGFRAME | WS_VISIBLE | WS_VSCROLL | LBS_SORT | LBS_NOTIFY, rect, this, IDC_LISTBOX_AUTOCOMPLETE );
autoCompleteListBox.SetFont( GetParent()->GetFont() );
autoCompleteListBox.ShowWindow( FALSE );
if ( autoCompleteListBox.GetSafeHwnd() == NULL ) {
autoCompleteListBox.Create( WS_DLGFRAME | WS_VISIBLE | WS_VSCROLL | LBS_SORT | LBS_NOTIFY, rect, this, IDC_LISTBOX_AUTOCOMPLETE );
autoCompleteListBox.SetFont( GetParent()->GetFont() );
autoCompleteListBox.ShowWindow( FALSE );
}
// create function parameter tool tip
funcParmToolTip.Create( WS_VISIBLE | WS_BORDER, rect, this, IDC_EDITBOX_FUNCPARMS );
funcParmToolTip.SetFont( GetParent()->GetFont() );
funcParmToolTip.ShowWindow( FALSE );
if ( funcParmToolTip.GetSafeHwnd() == NULL ) {
funcParmToolTip.Create( WS_VISIBLE | WS_BORDER, rect, this, IDC_EDITBOX_FUNCPARMS );
funcParmToolTip.SetFont( GetParent()->GetFont() );
funcParmToolTip.ShowWindow( FALSE );
}
}
/*
@@ -379,7 +450,7 @@ bool CSyntaxRichEditCtrl::LoadKeyWordsFromFile( const char *fileName ) {
src.ExpectTokenString( "}" );
keyword.keyWord = Mem_CopyString( name );
keyword.color = RGB( red, green, blue );
keyword.color = SREMakeReadableOnDark( RGB( red, green, blue ) );
keyword.description = Mem_CopyString( description );
keyWordsFromFile.Append( keyword );
@@ -391,7 +462,7 @@ bool CSyntaxRichEditCtrl::LoadKeyWordsFromFile( const char *fileName ) {
}
keyword.keyWord = NULL;
keyword.color = RGB( 255, 255, 255 );
keyword.color = SRE_DARK_DEFAULT_TEXT;
keyword.description = NULL;
keyWordsFromFile.Append( keyword );
@@ -548,6 +619,10 @@ CSyntaxRichEditCtrl::SetDefaultFont
================
*/
void CSyntaxRichEditCtrl::SetDefaultFont( int startCharIndex, int endCharIndex ) {
if ( m_TextDoc == NULL || m_DefaultFont == NULL ) {
return;
}
tom::ITextRange *range;
updateSyntaxHighlighting = false;
@@ -569,6 +644,10 @@ CSyntaxRichEditCtrl::SetColor
================
*/
void CSyntaxRichEditCtrl::SetColor( int startCharIndex, int endCharIndex, COLORREF foreColor, COLORREF backColor, bool bold ) {
if ( m_TextDoc == NULL ) {
return;
}
tom::ITextRange *range;
tom::ITextFont *font;
long prop;
@@ -602,6 +681,10 @@ CSyntaxRichEditCtrl::GetForeColor
================
*/
COLORREF CSyntaxRichEditCtrl::GetForeColor( int charIndex ) const {
if ( m_TextDoc == NULL ) {
return defaultColor;
}
tom::ITextRange *range;
tom::ITextFont *font;
long foreColor;
@@ -609,7 +692,7 @@ COLORREF CSyntaxRichEditCtrl::GetForeColor( int charIndex ) const {
m_TextDoc->Range( charIndex, charIndex, &range );
range->get_Font( &font );
font->get_BackColor( &foreColor );
font->get_ForeColor( &foreColor );
font->Release();
range->Release();
@@ -623,6 +706,10 @@ CSyntaxRichEditCtrl::GetBackColor
================
*/
COLORREF CSyntaxRichEditCtrl::GetBackColor( int charIndex ) const {
if ( m_TextDoc == NULL ) {
return DEFAULT_BACK_COLOR;
}
tom::ITextRange *range;
tom::ITextFont *font;
long backColor;
@@ -646,6 +733,10 @@ CSyntaxRichEditCtrl::HighlightSyntax
================
*/
void CSyntaxRichEditCtrl::HighlightSyntax( int startCharIndex, int endCharIndex ) {
if ( m_TextDoc == NULL || m_DefaultFont == NULL || !updateSyntaxHighlighting ) {
return;
}
int c, t, line, charIndex, textLength, syntaxStart, keyWordLength, keyWordIndex;
const char *keyWord;
CHARRANGE visRange;
@@ -654,6 +745,9 @@ void CSyntaxRichEditCtrl::HighlightSyntax( int startCharIndex, int endCharIndex
// get text length
GetTextRange( 0, GetTextLength(), text );
textLength = text.GetLength();
if ( textLength <= 0 ) {
return;
}
// make sure the indexes are within bounds
if ( startCharIndex < 0 ) {
@@ -684,11 +778,11 @@ void CSyntaxRichEditCtrl::HighlightSyntax( int startCharIndex, int endCharIndex
// never update beyond the visible range
if ( startCharIndex < visRange.cpMin ) {
SetColor( startCharIndex, visRange.cpMin - 1, SRE_COLOR_BLACK, INVALID_BACK_COLOR, false );
SetColor( startCharIndex, visRange.cpMin - 1, defaultColor, INVALID_BACK_COLOR, false );
startCharIndex = visRange.cpMin;
}
if ( visRange.cpMax < endCharIndex ) {
SetColor( visRange.cpMax, endCharIndex, SRE_COLOR_BLACK, INVALID_BACK_COLOR, false );
SetColor( visRange.cpMax, endCharIndex, defaultColor, INVALID_BACK_COLOR, false );
endCharIndex = visRange.cpMax;
if ( endCharIndex >= textLength ) {
endCharIndex = textLength - 1;
@@ -843,7 +937,7 @@ void CSyntaxRichEditCtrl::UpdateVisibleRange( void ) {
long backColor;
bool update = false;
if ( !updateSyntaxHighlighting ) {
if ( !updateSyntaxHighlighting || m_TextDoc == NULL || m_DefaultFont == NULL || GetTextLength() <= 0 ) {
return;
}
@@ -917,13 +1011,26 @@ CSyntaxRichEditCtrl::GetText
================
*/
void CSyntaxRichEditCtrl::GetText( idStr &text, int startCharIndex, int endCharIndex ) const {
tom::ITextRange *range;
BSTR bstr;
if ( m_TextDoc == NULL ) {
CString fallback;
GetTextRange( startCharIndex, endCharIndex, fallback );
text = fallback;
return;
}
tom::ITextRange *range = NULL;
BSTR bstr = NULL;
USES_CONVERSION;
m_TextDoc->Range( startCharIndex, endCharIndex, &range );
if ( m_TextDoc->Range( startCharIndex, endCharIndex, &range ) != S_OK || range == NULL ) {
text.Clear();
return;
}
range->get_Text( &bstr );
text = W2A( bstr );
if ( bstr != NULL ) {
::SysFreeString( bstr );
}
range->Release();
text.StripTrailingOnce( "\r" ); // remove last carriage return which is always added to a tom::ITextRange
}
@@ -945,6 +1052,10 @@ CSyntaxRichEditCtrl::FindNext
================
*/
bool CSyntaxRichEditCtrl::FindNext( const char *find, bool matchCase, bool matchWholeWords, bool searchForward ) {
if ( m_TextDoc == NULL ) {
return false;
}
long selStart, selEnd, flags, search, length, start;
tom::ITextRange *range;
@@ -994,6 +1105,10 @@ CSyntaxRichEditCtrl::ReplaceAll
================
*/
int CSyntaxRichEditCtrl::ReplaceAll( const char *find, const char *replace, bool matchCase, bool matchWholeWords ) {
if ( m_TextDoc == NULL ) {
return 0;
}
long selStart, selEnd, flags, search, length, start;
int numReplaced;
tom::ITextRange *range;
@@ -1034,6 +1149,12 @@ CSyntaxRichEditCtrl::ReplaceText
================
*/
void CSyntaxRichEditCtrl::ReplaceText( int startCharIndex, int endCharIndex, const char *replace ) {
if ( m_TextDoc == NULL ) {
SetSel( startCharIndex, endCharIndex );
ReplaceSel( replace, TRUE );
return;
}
tom::ITextRange *range;
CComBSTR bstr( replace );
@@ -1352,6 +1473,15 @@ CSyntaxRichEditCtrl::GoToLine
void CSyntaxRichEditCtrl::GoToLine( int line ) {
int index = LineIndex( line );
if ( index < 0 ) {
index = 0;
}
if ( m_TextDoc == NULL ) {
SetSel( index, index );
RedrawWindow();
return;
}
m_TextDoc->Freeze( NULL );
@@ -1756,6 +1886,10 @@ BOOL CSyntaxRichEditCtrl::OnMouseWheel( UINT nFlags, short zDelta, CPoint pt ) {
return TRUE;
}
if ( m_TextDoc == NULL ) {
return CRichEditCtrl::OnMouseWheel( nFlags, zDelta, pt );
}
m_TextDoc->Freeze( NULL );
LineScroll( -3 * ( (int) zDelta ) / WHEEL_DELTA, 0 );
@@ -1792,6 +1926,11 @@ CSyntaxRichEditCtrl::OnSize
================
*/
void CSyntaxRichEditCtrl::OnSize( UINT nType, int cx, int cy ) {
if ( m_TextDoc == NULL ) {
CRichEditCtrl::OnSize( nType, cx, cy );
return;
}
m_TextDoc->Freeze( NULL );
CRichEditCtrl::OnSize( nType, cx, cy );
@@ -1807,6 +1946,12 @@ CSyntaxRichEditCtrl::OnVScroll
================
*/
void CSyntaxRichEditCtrl::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar ) {
if ( m_TextDoc == NULL ) {
CRichEditCtrl::OnVScroll( nSBCode, nPos, pScrollBar );
SetFocus();
return;
}
m_TextDoc->Freeze( NULL );
CRichEditCtrl::OnVScroll( nSBCode, nPos, pScrollBar );
@@ -1868,16 +2013,14 @@ CSyntaxRichEditCtrl::OnChange
void CSyntaxRichEditCtrl::OnChange() {
long selStart, selEnd;
if ( !updateSyntaxHighlighting ) {
return;
if ( updateSyntaxHighlighting && m_TextDoc != NULL && m_DefaultFont != NULL ) {
GetSel( selStart, selEnd );
selStart = Min( selStart, updateRange.cpMin );
selEnd = Max( selEnd, updateRange.cpMax );
HighlightSyntax( selStart, selEnd );
}
GetSel( selStart, selEnd );
selStart = Min( selStart, updateRange.cpMin );
selEnd = Max( selEnd, updateRange.cpMax );
HighlightSyntax( selStart, selEnd );
// send EN_CHANGE notification to parent window
NMHDR pNMHDR;
pNMHDR.hwndFrom = GetSafeHwnd();
-1
View File
@@ -29,7 +29,6 @@ If you have questions concerning this license or the applicable additional terms
#define DEBUGGERAPP_H_
#include "../../sys/win32/win_local.h"
#include "../../framework/sync/Msg.h"
#ifndef REGISTRYOPTIONS_H_
#include "../common/RegistryOptions.h"
+7 -7
View File
@@ -29,13 +29,13 @@ If you have questions concerning this license or the applicable additional terms
#include "precompiled.h"
#pragma hdrstop
#include "../../game/gamesys/Event.h"
#include "../../game/gamesys/Class.h"
#include "../../game/script/Script_Program.h"
#include "../../game/script/Script_Interpreter.h"
#include "../../game/script/Script_Thread.h"
#include "../../game/script/Script_Compiler.h"
#include "../../framework/sync/Msg.h"
//#include "../../../doom3/game/gamesys/Event.h"
//#include "../../../doom3/game/gamesys/Class.h"
//#include "../../../doom3/game/script/Script_Program.h"
//#include "../../../doom3/game/script/Script_Interpreter.h"
//#include "../../../doom3/game/script/Script_Thread.h"
//#include "../../../doom3/game/script/Script_Compiler.h"
//#include "../../framework/sync/Msg.h"
#include "DebuggerApp.h"
#include "DebuggerServer.h"
+4 -4
View File
@@ -326,10 +326,10 @@ void DialogDeclBrowser::EditSelected( void ) const {
idStr typeName, declName;
GetDeclName( item, typeName, declName );
DialogScriptEditor *scriptEditor;
scriptEditor = new DialogScriptEditor;
scriptEditor->Create( IDD_DIALOG_SCRIPTEDITOR, GetParent() );
scriptEditor->OpenFile( typeName + "/" + declName + ( ( type == DECLTYPE_SCRIPT ) ? ".script" : ".gui" ) );
scriptEditor->ShowWindow( SW_SHOW );
//scriptEditor = new DialogScriptEditor;
//scriptEditor->Create( IDD_DIALOG_SCRIPTEDITOR, GetParent() );
//scriptEditor->OpenFile( typeName + "/" + declName + ( ( type == DECLTYPE_SCRIPT ) ? ".script" : ".gui" ) );
//scriptEditor->ShowWindow( SW_SHOW );
scriptEditor->SetFocus();
break;
}
+93 -1
View File
@@ -47,6 +47,7 @@ If you have questions concerning this license or the applicable additional terms
#define ID_XYDOCK_XYPAGE 0x7A03
#define ID_XYDOCK_GAMEPAGE 0x7A04
#define ID_XYDOCK_MODELVIEWPAGE 0x7A05
#define ID_XYDOCK_SCRIPTEDITORPAGE 0x7A06
#define ID_GAME_HOST 0x7A30
#define ID_GAME_FILL_FIT 0x7A40
@@ -1609,6 +1610,9 @@ int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
item.pszText = "Model View";
m_wndTabs.InsertItem(XYDOCK_TAB_MODELVIEW, &item);
item.pszText = "Script Editor";
m_wndTabs.InsertItem(XYDOCK_TAB_SCRIPTEDITOR, &item);
CString pageClass = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW),
@@ -1638,6 +1642,11 @@ int CXYDockWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
}
m_wndModelPage.ShowWindow(SW_HIDE);
if (!m_wndScriptPage.Create(&m_wndTabs, ID_XYDOCK_SCRIPTEDITORPAGE)) {
return -1;
}
m_wndScriptPage.ShowWindow(SW_HIDE);
if (!m_wndMenuBar.Create(&m_wndXYPage, 0x7A01)) {
return -1;
}
@@ -1777,6 +1786,7 @@ void CXYDockWnd::ShowActiveTab() {
const BOOL xyActive = (m_nActiveTab == XYDOCK_TAB_XY);
const BOOL gameActive = (m_nActiveTab == XYDOCK_TAB_GAME);
const BOOL modelActive = (m_nActiveTab == XYDOCK_TAB_MODELVIEW);
const BOOL scriptActive = (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR);
if (m_wndXYPage.GetSafeHwnd()) {
m_wndXYPage.ShowWindow(xyActive ? SW_SHOW : SW_HIDE);
@@ -1803,10 +1813,19 @@ void CXYDockWnd::ShowActiveTab() {
}
m_wndModelPage.SetActive(modelActive);
}
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.ShowWindow(scriptActive ? SW_SHOW : SW_HIDE);
if (scriptActive) {
m_wndScriptPage.SetWindowPos(&wndTop, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
m_wndScriptPage.SetActive(scriptActive);
}
}
void CXYDockWnd::SetActiveTab(int nTab) {
if (nTab != XYDOCK_TAB_XY && nTab != XYDOCK_TAB_GAME && nTab != XYDOCK_TAB_MODELVIEW) {
if (nTab != XYDOCK_TAB_XY && nTab != XYDOCK_TAB_GAME && nTab != XYDOCK_TAB_MODELVIEW && nTab != XYDOCK_TAB_SCRIPTEDITOR) {
nTab = XYDOCK_TAB_XY;
}
@@ -1835,6 +1854,9 @@ void CXYDockWnd::SetActiveTab(int nTab) {
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(FALSE);
}
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.SetActive(FALSE);
}
FocusGameWindow();
}
@@ -1851,10 +1873,33 @@ void CXYDockWnd::SetActiveTab(int nTab) {
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(TRUE);
}
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.SetActive(FALSE);
}
common->ActivateTool(true);
FocusModelView();
}
else if (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR) {
//
// Script Editor tab selected:
// - game HWND is deactivated
// - editor/tool input stays active
// - focus moves to the embedded syntax editor
//
if (m_wndGamePage.GetSafeHwnd()) {
m_wndGamePage.SetActive(FALSE);
}
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(FALSE);
}
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.SetActive(TRUE);
}
common->ActivateTool(true);
FocusScriptEditor();
}
else {
//
// XY tab selected:
@@ -1868,6 +1913,9 @@ void CXYDockWnd::SetActiveTab(int nTab) {
if (m_wndModelPage.GetSafeHwnd()) {
m_wndModelPage.SetActive(FALSE);
}
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.SetActive(FALSE);
}
common->ActivateTool(true);
FocusXYWindow();
@@ -1896,6 +1944,10 @@ void CXYDockWnd::SelectModelViewTab() {
SetActiveTab(XYDOCK_TAB_MODELVIEW);
}
void CXYDockWnd::SelectScriptEditorTab() {
SetActiveTab(XYDOCK_TAB_SCRIPTEDITOR);
}
BOOL CXYDockWnd::IsGameTabActive() const {
return (m_nActiveTab == XYDOCK_TAB_GAME) ? TRUE : FALSE;
}
@@ -1904,6 +1956,10 @@ BOOL CXYDockWnd::IsModelViewTabActive() const {
return (m_nActiveTab == XYDOCK_TAB_MODELVIEW) ? TRUE : FALSE;
}
BOOL CXYDockWnd::IsScriptEditorTabActive() const {
return (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR) ? TRUE : FALSE;
}
void CXYDockWnd::AttachGameWindow(HWND hGameWnd) {
m_wndGamePage.AttachGameWindow(hGameWnd);
m_wndGamePage.SetActive(IsGameTabActive());
@@ -1929,6 +1985,19 @@ void CXYDockWnd::FocusModelView() {
m_wndModelPage.FocusModelView();
}
void CXYDockWnd::FocusScriptEditor() {
m_wndScriptPage.FocusEditor();
}
DialogScriptEditor *CXYDockWnd::GetScriptEditor() {
return &m_wndScriptPage;
}
void CXYDockWnd::OpenScriptFile(const char *fileName) {
SelectScriptEditorTab();
m_wndScriptPage.OpenFile(fileName);
}
void CXYDockWnd::FocusXYWindow() {
m_wndMDIContainer.FocusXYWindow();
}
@@ -1976,6 +2045,11 @@ void CXYDockWnd::LayoutChildren() {
m_wndModelPage.LayoutChildren();
}
if (m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.MoveWindow(pageRect, TRUE);
m_wndScriptPage.LayoutChildren();
}
ShowActiveTab();
if (m_pToolBar && m_pToolBar->GetSafeHwnd() && m_wndXYPage.GetSafeHwnd()) {
@@ -2039,6 +2113,15 @@ BOOL CXYDockWnd::TrackMenuMnemonic(UINT nChar) {
return FALSE;
}
BOOL CXYDockWnd::PreTranslateMessage(MSG *pMsg) {
if (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR && m_wndScriptPage.GetSafeHwnd()) {
if (m_wndScriptPage.PreTranslateMessage(pMsg)) {
return TRUE;
}
}
return CWnd::PreTranslateMessage(pMsg);
}
void CXYDockWnd::OnSize(UINT nType, int cx, int cy) {
CWnd::OnSize(nType, cx, cy);
LayoutChildren();
@@ -2057,6 +2140,11 @@ LRESULT CXYDockWnd::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam) {
}
BOOL CXYDockWnd::OnCommand(WPARAM wParam, LPARAM lParam) {
if (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR && m_wndScriptPage.GetSafeHwnd()) {
m_wndScriptPage.SendMessage(WM_COMMAND, wParam, lParam);
return TRUE;
}
if (m_nActiveTab != XYDOCK_TAB_XY) {
return CWnd::OnCommand(wParam, lParam);
}
@@ -2092,6 +2180,10 @@ BOOL CXYDockWnd::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO
return TRUE;
}
if (m_nActiveTab == XYDOCK_TAB_SCRIPTEDITOR && m_wndScriptPage.GetSafeHwnd()) {
return m_wndScriptPage.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
if (m_nActiveTab != XYDOCK_TAB_XY) {
return FALSE;
}
+16 -2
View File
@@ -42,6 +42,7 @@ If you have questions concerning this license or the applicable additional terms
#include <afxcmn.h>
#include "ModelViewDock.h"
#include "../script/DialogScriptEditor.h"
class CXYWnd;
class CZWnd;
@@ -211,7 +212,7 @@ protected:
// CXYDockWnd
//
// Owns the embedded XY editor layout and the new docked game preview:
// [ tabs: XY | Game ]
// [ tabs: XY | Game | Model View | Script Editor ]
//
// XY tab:
// [ menu bar ]
@@ -222,6 +223,11 @@ protected:
// [ game command strip / fill controls ]
// [ hosted game HWND ]
//
// Script Editor tab:
// [ dark command strip ]
// [ syntax/intellisense editor ]
// [ status strip ]
//
// The docked Z window starts at 5% of the MDI container width. The divider in
// the MDI client can be dragged to resize the Z and XY top panes interactively.
//=============================================================================
@@ -264,23 +270,31 @@ public:
HWND GetDockedGameWindow() const;
BOOL IsGameTabActive() const;
BOOL IsModelViewTabActive() const;
BOOL IsScriptEditorTabActive() const;
void SelectXYTab();
void SelectGameTab();
void SelectModelViewTab();
void SelectScriptEditorTab();
void FocusGameWindow();
void FocusXYWindow();
void FocusModelView();
void FocusScriptEditor();
DialogScriptEditor *GetScriptEditor();
void OpenScriptFile(const char *fileName);
virtual BOOL PreTranslateMessage(MSG *pMsg);
protected:
enum {
XYDOCK_TAB_XY = 0,
XYDOCK_TAB_GAME = 1,
XYDOCK_TAB_MODELVIEW = 2
XYDOCK_TAB_MODELVIEW = 2,
XYDOCK_TAB_SCRIPTEDITOR = 3
};
CTabCtrl m_wndTabs;
CWnd m_wndXYPage;
CGameDockWnd m_wndGamePage;
CModelViewDockWnd m_wndModelPage;
DialogScriptEditor m_wndScriptPage;
CXYMenuBar m_wndMenuBar;
CXYMDIContainerWnd m_wndMDIContainer;
CToolBar *m_pToolBar;
File diff suppressed because it is too large Load Diff
+123 -18
View File
@@ -31,43 +31,82 @@ If you have questions concerning this license or the applicable additional terms
#pragma once
#include "../comafx/CSyntaxRichEditCtrl.h"
class CScriptEditorCtrl;
// DialogScriptEditor dialog
class DialogScriptEditor : public CDialog {
//=============================================================================
// DialogScriptEditor
//
// Dockable Script Editor tab page. This version intentionally does not use
// the old syntax-rich edit control. The text editor is a custom dark-themed
// CWnd owned by DialogScriptEditor, with double-buffered manual drawing,
// caret/selection handling, syntax coloring, find/replace, virtual pk5 script
// opening, automatic incremental IntelliSense, signature help, and Save As/New
// file support.
//=============================================================================
class DialogScriptEditor : public CWnd {
DECLARE_DYNAMIC(DialogScriptEditor)
public:
DialogScriptEditor( CWnd* pParent = NULL ); // standard constructor
DialogScriptEditor( CWnd* pParent = NULL );
virtual ~DialogScriptEditor();
BOOL Create( CWnd *pParent, UINT nID );
BOOL Create( const RECT &rect, CWnd *pParent, UINT nID );
void OpenFile( const char *fileName );
bool SaveFile( void );
bool SaveFileAs( void );
bool ReloadFile( void );
void NewFile( void );
bool HasOpenFile( void ) const;
bool IsDirty( void ) const;
const char * GetFileName( void ) const;
void SetActive( BOOL bActive );
void FocusEditor( void );
void LayoutChildren( void );
void ShowIntelliSense( bool forced = false );
void HideIntelliSense( void );
static DialogScriptEditor *GetPrimaryEditor( void );
//{{AFX_VIRTUAL(DialogScriptEditor)
virtual BOOL OnInitDialog();
virtual void DoDataExchange( CDataExchange* pDX ); // DDX/DDV support
virtual BOOL PreTranslateMessage( MSG* pMsg );
virtual BOOL OnCmdMsg( UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo );
//}}AFX_VIRTUAL
protected:
//{{AFX_MSG(DialogScriptEditor)
afx_msg BOOL OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult );
afx_msg void OnSetFocus( CWnd *pOldWnd );
afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
afx_msg void OnDestroy();
afx_msg void OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized );
afx_msg void OnMove( int x, int y );
afx_msg void OnSize( UINT nType, int cx, int cy );
afx_msg void OnSizing( UINT nSide, LPRECT lpRect );
afx_msg void OnSetFocus( CWnd *pOldWnd );
afx_msg void OnTimer( UINT_PTR nIDEvent );
afx_msg BOOL OnEraseBkgnd( CDC *pDC );
afx_msg HBRUSH OnCtlColor( CDC *pDC, CWnd *pWnd, UINT nCtlColor );
afx_msg void OnPaint();
afx_msg void OnDrawItem( int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct );
afx_msg void OnMeasureItem( int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct );
afx_msg BOOL OnToolTipNotify( UINT id, NMHDR *pNMHDR, LRESULT *pResult );
afx_msg void OnFileNew();
afx_msg void OnFileOpen();
afx_msg void OnFileSaveAs();
afx_msg void OnEditGoToLine();
afx_msg void OnEditFind();
afx_msg void OnEditFindNext();
afx_msg void OnEditReplace();
afx_msg void OnEditShowIntelliSense();
afx_msg LRESULT OnFindDialogMessage( WPARAM wParam, LPARAM lParam );
afx_msg LRESULT OnDeferredIntelliSense( WPARAM wParam, LPARAM lParam );
afx_msg LRESULT OnIntelliSenseKey( WPARAM wParam, LPARAM lParam );
afx_msg void OnEnChangeEdit( NMHDR *pNMHDR, LRESULT *pResult );
afx_msg void OnEnInputEdit( NMHDR *pNMHDR, LRESULT *pResult );
afx_msg void OnEditorSelectionChanged( NMHDR *pNMHDR, LRESULT *pResult );
afx_msg void OnIntelliSenseDblClick();
afx_msg void OnIntelliSenseSelChange();
afx_msg void OnBnClickedOk();
afx_msg void OnBnClickedCancel();
//}}AFX_MSG
@@ -75,30 +114,96 @@ protected:
DECLARE_MESSAGE_MAP()
private:
//{{AFX_DATA(DialogScriptEditor)
enum { IDD = IDD_DIALOG_SCRIPTEDITOR };
CStatusBarCtrl statusBar;
CSyntaxRichEditCtrl scriptEdit;
CStatic m_titleLabel;
CStatic m_pathLabel;
CStatic m_statusLine;
CStatic m_languageLabel;
CStatic m_signatureHelp;
CScriptEditorCtrl *scriptEdit;
CListBox m_intellisenseList;
CButton newButton;
CButton openButton;
CButton saveAsButton;
CButton okButton;
CButton cancelButton;
//}}AFX_DATA
CButton findButton;
CButton replaceButton;
CButton goToButton;
CFont m_editorFont;
CFont m_uiFont;
CBrush m_backBrush;
CBrush m_panelBrush;
CBrush m_editBrush;
CBrush m_hotBrush;
static toolTip_t toolTips[];
static DialogScriptEditor *primaryEditor;
HACCEL m_hAccel;
CRect initialRect;
CFindReplaceDialog *findDlg;
CFindReplaceDialog *findDlg;
CString findStr;
CString replaceStr;
bool matchCase;
bool matchWholeWords;
bool searchForward;
idStr fileName;
int firstLine;
idStr loadedText;
int firstLine;
bool isDirty;
bool internalChange;
BOOL isActive;
bool m_intelliSenseReady;
bool m_intelliSenseCoreReady;
bool m_virtualFileListReady;
bool m_backgroundScanActive;
int m_backgroundScanNextFile;
UINT_PTR m_intelliSenseTimer;
int m_indexedScriptFiles;
int m_indexedSymbols;
private:
void InitScriptEvents( void );
void InitEditorChrome( void );
void ApplyDarkTheme( void );
void ConfigureEditorForFile( const char *fileName );
void EnsureIntelliSenseCore( void );
void EnsureVirtualScriptFileList( bool forceRebuild = false );
void StartIntelliSenseBackgroundScan( bool forceRebuild = false );
void IndexNextScriptFiles( int maxFiles );
void UpdateLiveCompletions( void );
void BuildIntelliSenseDatabase( bool forceRebuild = false );
void RebuildVirtualScriptFileList( void );
bool OpenFileFromDialog( void );
bool PromptSavePath( CString &selectedPath );
bool SaveFileAsDialog( void );
bool LoadTextFromFile( const char *path, idStr &text ) const;
bool WriteTextToFile( const char *path, const char *text, int textLength ) const;
bool IsNativeFilePath( const char *path ) const;
void SetDirty( bool dirty );
void UpdateTitle( void );
void UpdateStatusBar( void );
void UpdateLanguageLabel( const char *extension );
void SetEditorTextNormalized( const char *text );
bool GetEditorTextNormalized( idStr &text ) const;
bool ConfirmDiscardChanges( void );
bool HandleIntelliSenseKey( MSG *msg );
bool IsMemberCompletionContext( long wordStart ) const;
bool IsFunctionArgumentContext( void ) const;
void CompleteIntelliSense( void );
void PopulateIntelliSense( const CString &prefix, bool forced );
bool GetFunctionSignatureBeforeCaret( CString &functionName, CString &signature, int &argumentIndex ) const;
void ShowFunctionParameterHint( void );
void HideFunctionParameterHint( void );
void PositionParameterHint( void );
CString GetCurrentWord( long *wordStart = NULL, long *wordEnd = NULL ) const;
bool IsIdentifierChar( int ch ) const;
bool StartsWithNoCase( const CString &text, const CString &prefix ) const;
void InsertCompletion( const CString &completion );
void PositionIntelliSenseWindow( void );
};
DialogScriptEditor *ScriptEditorGetPrimaryEditor( void );
#endif /* !__DIALOGSCRIPTEDITOR_H__ */