1 /*
2     SuperCollider Qt IDE
3     Copyright (c) 2012 Jakob Leben & Tim Blechmann
4     http://www.audiosynth.com
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19 */
20 
21 #pragma once
22 
23 #include <QWidget>
24 #include <QTabBar>
25 #include <QAction>
26 #include <QPushButton>
27 #include <QToolButton>
28 #include <QLineEdit>
29 #include <QCheckBox>
30 #include <QLabel>
31 #include <QGridLayout>
32 #include <QTextDocument>
33 #include <QSplitter>
34 
35 namespace ScIDE {
36 
37 class CodeEditorBox;
38 class Document;
39 class DocumentManager;
40 class GenericCodeEditor;
41 class Main;
42 class MultiSplitter;
43 struct Session;
44 class SignalMultiplexer;
45 
46 namespace Settings {
47 class Manager;
48 }
49 
50 class EditorTabBar : public QTabBar {
51     Q_OBJECT
52 
53 public:
54     explicit EditorTabBar(QWidget* parent = nullptr);
55 
56 private slots:
57     void onCloseTab();
58     void onCloseOtherTabs();
59     void onCloseTabsToTheRight();
60 
61 private:
62     void mousePressEvent(QMouseEvent* event) override final;
63     void mouseDoubleClickEvent(QMouseEvent* event) override final;
64 
65     void showContextMenu(QMouseEvent* event);
66 
67     int mTabUnderCursor;
68 };
69 
70 class MultiEditor : public QWidget {
71     Q_OBJECT
72 
73 public:
74     enum ActionRole {
75         // Edit
76         Undo,
77         Redo,
78         Cut,
79         Copy,
80         Paste,
81         IndentLineOrRegion,
82         TriggerAutoCompletion,
83         TriggerMethodCallAid,
84         ToggleComment,
85         ToggleOverwriteMode,
86 
87         CopyLineUp,
88         CopyLineDown,
89         MoveLineUp,
90         MoveLineDown,
91         DeleteWord,
92 
93         GotoPreviousBlock,
94         GotoNextBlock,
95         SelectEnclosingBlock,
96 
97         GotoPreviousRegion,
98         GotoNextRegion,
99         GotoPreviousEmptyLine,
100         GotoNextEmptyLine,
101 
102         SelectRegion,
103 
104         // View
105         DocClose,
106         EnlargeFont,
107         ShrinkFont,
108         ResetFontSize,
109         ShowWhitespace,
110         ShowLinenumber,
111         IndentWithSpaces,
112         ShowAutocompleteHelp,
113 
114         NextDocument,
115         PreviousDocument,
116         SwitchDocument,
117 
118         SplitHorizontally,
119         SplitVertically,
120         RemoveCurrentSplit,
121         RemoveAllSplits,
122 
123         // Language
124         EvaluateCurrentDocument,
125         EvaluateRegion,
126         EvaluateLine,
127 
128         ActionRoleCount
129     };
130 
131     MultiEditor(Main*, QWidget* parent = 0);
132 
tabCount()133     int tabCount() { return mTabs->count(); }
134     Document* documentForTab(int index);
135     int tabForDocument(Document* doc);
136 
137     GenericCodeEditor* currentEditor();
currentBox()138     CodeEditorBox* currentBox() { return mCurrentEditorBox; }
139     void split(Qt::Orientation direction);
140 
action(ActionRole role)141     QAction* action(ActionRole role) { return mActions[role]; }
142 
143     void saveSession(Session*);
144     void switchSession(Session*);
145 
146 signals:
147     void currentDocumentChanged(Document*);
148     void splitViewActivated();
149     void splitViewDeactivated();
150     void updateDockletOrder(int, int);
151 
152 public slots:
153 
154     void setCurrent(Document*);
155 
156     void showNextDocument();
157     void showPreviousDocument();
158     void switchDocument();
159 
splitHorizontally()160     void splitHorizontally() { split(Qt::Horizontal); }
splitVertically()161     void splitVertically() { split(Qt::Vertical); }
162     void removeCurrentSplit();
163     void removeAllSplits();
164 
165     void setShowWhitespace(bool on);
166     void setShowLinenumber(bool on);
167 
168     void setShowAutocompleteHelp(bool on);
169 
170     void updateTabsOrder(QList<Document*>);
171 
172 private slots:
173     void applySettings(Settings::Manager*);
174     void onOpen(Document*, int initialCursorPosition, int selectionLength);
175     void onClose(Document*);
176     void show(Document*, int cursorPosition = -1, int selectionLenght = 0);
177     void update(Document*);
178     void onCloseRequest(int index);
179     void onCurrentTabChanged(int index);
180     void onCurrentEditorChanged(GenericCodeEditor*);
181     void onBoxActivated(CodeEditorBox*);
182     void onDocModified(Document*);
183     void updateDocOrder(int, int);
184 
185 private:
186     void makeSignalConnections();
187     void breakSignalConnections();
188     void createActions();
189     void updateActions();
190 
191     /**
192      * Put a new doc into the editor. If `doc` is already opened, this simply returns its current index.
193      *
194      * @param doc The doc to insert.
195      * @param insertIndex Index at which to insert. If negative, the doc is inserted after the current tab.
196      * @return The index of the tab.
197      */
198     int insertTab(Document* doc, int insertIndex = -1);
199     CodeEditorBox* newBox(MultiSplitter*);
200     void setCurrentBox(CodeEditorBox*);
201     void setCurrentEditor(GenericCodeEditor*);
202     void loadBoxState(CodeEditorBox* box, const QVariantList& data, const QList<Document*>& documentList);
203     void loadSplitterState(MultiSplitter*, const QVariantMap& data, const QList<Document*>& documentList);
204     void showEditorTabs(bool);
205     void activateComboBoxWhenSplitting();
206     void setMainComboBoxOption();
207 
208     QAction* mActions[ActionRoleCount];
209 
210     SignalMultiplexer* mEditorSigMux;
211     SignalMultiplexer* mBoxSigMux;
212 
213     // gui
214     QTabBar* mTabs;
215     CodeEditorBox* mCurrentEditorBox;
216     MultiSplitter* mSplitter;
217     QIcon mDocModifiedIcon;
218     QVBoxLayout* multiEditorLayout;
219 };
220 
221 } // namespace ScIDE
222