torque-ide/src/torqueidestc.cpp

361 lines
11 KiB
C++

/*
* Torque IDE -- An open source integrated development environment for the
* Torque Game Engine
*
* Copyright (C) 2005 Robert Pierce
** Adapted from wxWidgets STC example
*
* Refer to the file CONTRIB.txt for the people who have helped.
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
// For compilers that supports precompilation, include "wx/wx.h"
#include <wx/wxprec.h>
#include <wx/filedlg.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/file.h>
#include <wx/filename.h>
#include "torqueidestc.h"
TorqueIDESTC::TorqueIDESTC(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style)
: wxStyledTextCtrl(parent, id, pos, size, style)
{
filename = _T("");
lineNumID = 0;
dividerID = 1;
foldingID = 2;
// initialize language
language = NULL;
// default font for all styles
SetViewEOL(commonPrefs.displayEOLEnable);
SetIndentationGuides(commonPrefs.indentGuideEnable);
SetEdgeMode(commonPrefs.longLineOnEnable? wxSTC_EDGE_LINE: wxSTC_EDGE_NONE);
SetViewWhiteSpace(commonPrefs.whiteSpaceEnable? wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE);
SetOvertype(commonPrefs.overTypeInitial);
SetReadOnly(commonPrefs.readOnlyInitial);
SetWrapMode(commonPrefs.wrapModeInitial? wxSTC_WRAP_WORD: wxSTC_WRAP_NONE);
wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
StyleSetFont(wxSTC_STYLE_DEFAULT, font);
StyleSetForeground(wxSTC_STYLE_DEFAULT, wxColour (_T("BLACK")));
StyleSetBackground(wxSTC_STYLE_DEFAULT, wxColour (_T("WHITE")));
StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour (_T("DARK GREY")));
StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour (_T("WHITE")));
StyleSetForeground(wxSTC_STYLE_INDENTGUIDE, wxColour (_T("DARK GREY")));
InitializePrefs(DEFAULT_LANGUAGE);
// set visibility
SetVisiblePolicy(wxSTC_VISIBLE_STRICT|wxSTC_VISIBLE_SLOP, 1);
SetXCaretPolicy(wxSTC_CARET_EVEN|wxSTC_VISIBLE_STRICT|wxSTC_CARET_SLOP, 1);
SetYCaretPolicy(wxSTC_CARET_EVEN|wxSTC_VISIBLE_STRICT|wxSTC_CARET_SLOP, 1);
// markers
MarkerDefine(wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_CIRCLEMINUS);
MarkerDefine(wxSTC_MARKNUM_FOLDER, wxSTC_MARK_CIRCLEPLUS);
MarkerDefine(wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_VLINE);
MarkerDefine(wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_LCORNERCURVE);
MarkerDefine(wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_CIRCLEPLUSCONNECTED);
MarkerDefine(wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_CIRCLEMINUSCONNECTED);
MarkerDefine(wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_TCORNERCURVE);
// miscelaneous
lineNumMargin = TextWidth(wxSTC_STYLE_LINENUMBER, _T("_999999"));
foldingMargin = 16;
CmdKeyClear(wxSTC_KEY_TAB, 0); // this is done by the menu accelerator key
SetLayoutCache(wxSTC_CACHE_PAGE);
}
TorqueIDESTC::~TorqueIDESTC()
{
}
wxString TorqueIDESTC::DeterminePrefs(const wxString &file)
{
LanguageInfo const* curInfo;
// Determine Language Filepatterns
int languageNum;
for (languageNum = 0; languageNum < languagePrefsSize; languageNum++) {
curInfo = &languagePrefs[languageNum];
wxString filepattern = curInfo->filepattern;
filepattern.Lower();
while (!filepattern.IsEmpty()) {
wxString cur = filepattern.BeforeFirst (';');
if ((cur == file) || (cur == (file.BeforeLast ('.') + _T(".*"))) || (cur == (_T("*.") + file.AfterLast ('.'))))
{
return curInfo->name;
}
filepattern = filepattern.AfterFirst (';');
}
}
return wxEmptyString;
}
bool TorqueIDESTC::InitializePrefs (const wxString &name)
{
// Init Styles
StyleClearAll();
LanguageInfo const* curInfo = NULL;
// Determine Language
bool found = false;
int languageNum;
for(languageNum = 0; languageNum < languagePrefsSize; languageNum++) {
curInfo = &languagePrefs[languageNum];
if (curInfo->name == name) {
found = true;
break;
}
}
if(!found)
{
return false;
}
// Set Lexer and Language
SetLexer(curInfo->lexer);
language = curInfo;
// Set Margin for Line Numbers
SetMarginType(lineNumID, wxSTC_MARGIN_NUMBER);
StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(_T("DARK GREY")));
StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(_T("WHITE")));
SetMarginWidth(lineNumID, 0); // Start out invisible
// Default Fonts for Styles
int Num;
for(Num = 0; Num < wxSTC_STYLE_LASTPREDEFINED; Num++) {
wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
StyleSetFont(Num, font);
}
// Set Common Styles
StyleSetForeground(wxSTC_STYLE_DEFAULT, wxColour (_T("DARK GREY")));
StyleSetForeground(wxSTC_STYLE_INDENTGUIDE, wxColour (_T("DARK GREY")));
// Init Settings
if(commonPrefs.syntaxEnable) {
int keywordNum = 0;
for(Num = 0; Num < STYLE_TYPES_COUNT; Num++) {
if(curInfo->styles[Num].type == -1) continue;
const StyleInfo &curType = stylePrefs [curInfo->styles[Num].type];
wxFont font(curType.fontsize, wxMODERN, wxNORMAL, wxNORMAL, false, curType.fontname);
StyleSetFont(Num, font);
if(curType.foreground) {
StyleSetForeground(Num, wxColour (curType.foreground));
}
if(curType.background) {
StyleSetBackground(Num, wxColour (curType.background));
}
StyleSetBold(Num, (curType.fontstyle & TORQUEIDESTC_STYLE_BOLD) > 0);
StyleSetItalic(Num, (curType.fontstyle & TORQUEIDESTC_STYLE_ITALIC) > 0);
StyleSetUnderline(Num, (curType.fontstyle & TORQUEIDESTC_STYLE_UNDERL) > 0);
StyleSetVisible(Num, (curType.fontstyle & TORQUEIDESTC_STYLE_HIDDEN) == 0);
StyleSetCase(Num, curType.lettercase);
const wxChar *pwords = curInfo->styles[Num].words;
if(pwords) {
SetKeyWords(keywordNum, pwords);
keywordNum += 1;
}
}
}
// Set Margin as unused
SetMarginType(dividerID, wxSTC_MARGIN_SYMBOL);
SetMarginWidth(dividerID, 0);
SetMarginSensitive(dividerID, false);
// Folding
SetMarginType(foldingID, wxSTC_MARGIN_SYMBOL);
SetMarginMask(foldingID, wxSTC_MASK_FOLDERS);
StyleSetBackground(foldingID, wxColour (_T("WHITE")));
SetMarginWidth(foldingID, 0);
SetMarginSensitive(foldingID, false);
if (commonPrefs.foldEnable) {
SetMarginWidth(foldingID, curInfo->folds != 0? foldingMargin: 0);
SetMarginSensitive(foldingID, curInfo->folds != 0);
SetProperty(_T("fold"), curInfo->folds != 0? _T("1"): _T("0"));
SetProperty(_T("fold.comment"), (curInfo->folds & TORQUEIDESTC_FOLD_COMMENT) > 0? _T("1"): _T("0"));
SetProperty(_T("fold.compact"), (curInfo->folds & TORQUEIDESTC_FOLD_COMPACT) > 0? _T("1"): _T("0"));
SetProperty(_T("fold.preprocessor"), (curInfo->folds & TORQUEIDESTC_FOLD_PREPROC) > 0? _T("1"): _T("0"));
SetProperty(_T("fold.html"), (curInfo->folds & TORQUEIDESTC_FOLD_HTML) > 0? _T("1"): _T("0"));
SetProperty(_T("fold.html.preprocessor"), (curInfo->folds & TORQUEIDESTC_FOLD_HTMLPREP) > 0? _T("1"): _T("0"));
SetProperty(_T("fold.comment.python"), (curInfo->folds & TORQUEIDESTC_FOLD_COMMENTPY) > 0? _T("1"): _T("0"));
SetProperty(_T("fold.quotes.python"), (curInfo->folds & TORQUEIDESTC_FOLD_QUOTESPY) > 0? _T("1"): _T("0"));
}
SetFoldFlags(wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED | wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED);
// Set Tabs and Indentation
SetTabWidth(4);
SetUseTabs(true);
SetTabIndents(true);
SetBackSpaceUnIndents(true);
SetIndent(commonPrefs.indentEnable? 4: 0);
// Others
SetViewEOL(commonPrefs.displayEOLEnable);
SetIndentationGuides(commonPrefs.indentGuideEnable);
SetEdgeColumn(80);
SetEdgeMode(commonPrefs.longLineOnEnable? wxSTC_EDGE_LINE: wxSTC_EDGE_NONE);
SetViewWhiteSpace(commonPrefs.whiteSpaceEnable? wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE);
SetOvertype(commonPrefs.overTypeInitial);
SetReadOnly(commonPrefs.readOnlyInitial);
SetWrapMode(commonPrefs.wrapModeInitial? wxSTC_WRAP_WORD: wxSTC_WRAP_NONE);
return true;
}
bool TorqueIDESTC::LoadFile()
{
// Get Filename
if (!filename)
{
wxFileDialog dlg (this, _T("Open file"), _T(""), _T(""), _T("Any file (*)|*"), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR);
if (dlg.ShowModal() != wxID_OK) return false;
filename = dlg.GetPath();
}
// Load File
return LoadFile(filename);
}
bool TorqueIDESTC::LoadFile(const wxString &file)
{
// Load File and clear undo
if (!file.IsEmpty())
{
filename = file;
}
// wxFile file(filename);
// if (!file.IsOpened()) return false;
ClearAll();
// long lng = file.Length ();
// if (lng > 0) {
// wxString buf;
// wxChar *buff = buf.GetWriteBuf (lng);
// file.Read (buff, lng);
// buf.UngetWriteBuf ();
// InsertText (0, buf);
// }
// file.Close();
wxStyledTextCtrl::LoadFile(file);
EmptyUndoBuffer();
// Determine Lexer Language
wxFileName fname(file);
InitializePrefs(DeterminePrefs(fname.GetFullName()));
return true;
}
bool TorqueIDESTC::SaveFile()
{
// return if no change
if (!Modified()) return true;
// Get Filename
if (!filename) {
wxFileDialog dlg (this, _T("Save file"), _T(""), _T(""), _T("Any file (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (dlg.ShowModal() != wxID_OK) return false;
filename = dlg.GetPath();
}
// Save File
return SaveFile(filename);
}
bool TorqueIDESTC::SaveFile(const wxString &file)
{
// return if no change
if (!Modified()) return true;
// // Save file and clear undo
// if (!filename.IsEmpty()) m_filename = filename;
// wxFile file (m_filename, wxFile::write);
// if (!file.IsOpened()) return false;
// wxString buf = GetText();
// bool okay = file.Write (buf);
// file.Close();
// if (!okay) return false;
// EmptyUndoBuffer();
// SetSavePoint();
// return true;
return wxStyledTextCtrl::SaveFile(file);
}
bool TorqueIDESTC::Modified ()
{
// Return Modified State
return(GetModify() && !GetReadOnly());
}
/**
* Events and Event Handlers
*/
BEGIN_EVENT_TABLE(TorqueIDESTC, wxStyledTextCtrl)
EVT_SIZE(TorqueIDESTC::OnSize)
EVT_STC_MARGINCLICK(wxID_ANY, TorqueIDESTC::OnMarginClick)
EVT_STC_CHARADDED(wxID_ANY, TorqueIDESTC::OnCharAdded)
END_EVENT_TABLE()
void TorqueIDESTC::OnSize(wxSizeEvent& event)
{
int x = GetClientSize().x + (commonPrefs.lineNumberEnable? lineNumMargin: 0) + (commonPrefs.foldEnable? foldingMargin: 0);
if (x > 0) SetScrollWidth(x);
event.Skip();
}
void TorqueIDESTC::OnMarginClick(wxStyledTextEvent &event) {
if(event.GetMargin() == 2) {
int lineClick = LineFromPosition (event.GetPosition());
int levelClick = GetFoldLevel (lineClick);
if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0) {
ToggleFold (lineClick);
}
}
}
void TorqueIDESTC::OnCharAdded(wxStyledTextEvent &event)
{
char chr = (char)event.GetKey();
int currentLine = GetCurrentLine();
// Change this if support for mac files with \r is needed
if (chr == '\n') {
int lineInd = 0;
if(currentLine > 0) {
lineInd = GetLineIndentation(currentLine - 1);
}
if(lineInd == 0) return;
SetLineIndentation(currentLine, lineInd);
GotoPos(PositionFromLine (currentLine) + lineInd);
}
}