1 /*
2  * PanmirrorToolbarCommands.java
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 package org.rstudio.studio.client.panmirror.command;
17 
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 
22 import org.rstudio.core.client.Debug;
23 import org.rstudio.core.client.StringUtil;
24 import org.rstudio.studio.client.palette.model.CommandPaletteEntryProvider;
25 import org.rstudio.studio.client.palette.model.CommandPaletteItem;
26 
27 import com.google.gwt.aria.client.MenuitemRole;
28 import com.google.gwt.aria.client.Roles;
29 import org.rstudio.studio.client.palette.ui.CommandPalette;
30 
31 public class PanmirrorToolbarCommands implements CommandPaletteEntryProvider
32 {
PanmirrorToolbarCommands(PanmirrorCommand[] commands)33    public PanmirrorToolbarCommands(PanmirrorCommand[] commands)
34    {
35       PanmirrorCommandIcons icons = PanmirrorCommandIcons.INSTANCE;
36 
37       // init commands
38       commands_ = commands;
39 
40       // text editing
41       add(PanmirrorCommands.Undo, "Undo");
42       add(PanmirrorCommands.Redo, "Redo");
43       add(PanmirrorCommands.SelectAll, "Select All");
44 
45       // formatting
46       add(PanmirrorCommands.Strong, "Bold", icons.BOLD);
47       add(PanmirrorCommands.Em, "Italic", icons.ITALIC);
48       add(PanmirrorCommands.Code, "Code", icons.CODE);
49       add(PanmirrorCommands.Strikeout, "Strikeout");
50       add(PanmirrorCommands.Superscript, "Superscript");
51       add(PanmirrorCommands.Subscript, "Subscript");
52       add(PanmirrorCommands.Smallcaps, "Small Caps");
53       add(PanmirrorCommands.Underline, "Underline", icons.UNDERLINE);
54       add(PanmirrorCommands.Span, "Span...");
55       add(PanmirrorCommands.Paragraph, "Normal", Roles.getMenuitemradioRole());
56       add(PanmirrorCommands.Heading1, "Heading 1", Roles.getMenuitemradioRole());
57       add(PanmirrorCommands.Heading2, "Heading 2", Roles.getMenuitemradioRole());
58       add(PanmirrorCommands.Heading3, "Heading 3", Roles.getMenuitemradioRole());
59       add(PanmirrorCommands.Heading4, "Heading 4", Roles.getMenuitemradioRole());
60       add(PanmirrorCommands.Heading5, "Heading 5", Roles.getMenuitemradioRole());
61       add(PanmirrorCommands.Heading6, "Heading 6", Roles.getMenuitemradioRole());
62       add(PanmirrorCommands.CodeBlock, "Code Block", Roles.getMenuitemradioRole());
63       add(PanmirrorCommands.CodeBlockFormat, "Code Block...");
64 
65       add(PanmirrorCommands.Blockquote, "Blockquote", Roles.getMenuitemcheckboxRole(), icons.BLOCKQUOTE);
66       add(PanmirrorCommands.LineBlock, "Line Block", Roles.getMenuitemcheckboxRole());
67       add(PanmirrorCommands.Div, "Div...");
68       add(PanmirrorCommands.AttrEdit, "Edit Attributes...");
69       add(PanmirrorCommands.ClearFormatting, "Clear Formatting", icons.CLEAR_FORMATTING);
70 
71       // raw
72       add(PanmirrorCommands.TexInline, "TeX Inline", Roles.getMenuitemcheckboxRole());
73       add(PanmirrorCommands.TexBlock, "TeX Block", Roles.getMenuitemcheckboxRole());
74       add(PanmirrorCommands.HTMLInline, "HTML Inline...");
75       add(PanmirrorCommands.HTMLBlock, "HTML Block", Roles.getMenuitemcheckboxRole());
76       add(PanmirrorCommands.RawInline, "Raw Inline...");
77       add(PanmirrorCommands.RawBlock, "Raw Block...");
78 
79       // chunk
80       add(PanmirrorCommands.RCodeChunk, "R");
81       add(PanmirrorCommands.BashCodeChunk, "Bash");
82       add(PanmirrorCommands.D3CodeChunk, "D3");
83       add(PanmirrorCommands.PythonCodeChunk, "Python");
84       add(PanmirrorCommands.RcppCodeChunk, "Rcpp");
85       add(PanmirrorCommands.SQLCodeChunk, "SQL");
86       add(PanmirrorCommands.StanCodeChunk, "Stan");
87 
88       // lists
89       add(PanmirrorCommands.BulletList, "Bulleted List", Roles.getMenuitemcheckboxRole(), icons.BULLET_LIST);
90       add(PanmirrorCommands.OrderedList, "Numbered List", Roles.getMenuitemcheckboxRole(), icons.NUMBERED_LIST);
91       add(PanmirrorCommands.TightList, "Tight List", Roles.getMenuitemcheckboxRole());
92       add(PanmirrorCommands.ListItemSink, "Sink Item");
93       add(PanmirrorCommands.ListItemLift, "Lift Item");
94       add(PanmirrorCommands.ListItemCheck, "Item Checkbox");
95       add(PanmirrorCommands.ListItemCheckToggle, "Item Checked", Roles.getMenuitemcheckboxRole());
96       add(PanmirrorCommands.EditListProperties, "List Attributes...");
97 
98       // tables
99       add(PanmirrorCommands.TableInsertTable, "Insert Table...", icons.TABLE);
100       add(PanmirrorCommands.TableToggleHeader, "Table Header", Roles.getMenuitemcheckboxRole());
101       add(PanmirrorCommands.TableToggleCaption, "Table Caption", Roles.getMenuitemcheckboxRole());
102       add(PanmirrorCommands.TableAddColumnAfter, "Table:::Insert Column Right", "Insert %d Columns Right", null);
103       add(PanmirrorCommands.TableAddColumnBefore, "Table:::Insert Column Left", "Insert %d Columns Left", null);
104       add(PanmirrorCommands.TableDeleteColumn, "Table:::Delete Column", "Table:::Delete %d Columns", null);
105       add(PanmirrorCommands.TableAddRowAfter, "Table:::Insert Row Below", "Table:::Insert %d Rows Below", null);
106       add(PanmirrorCommands.TableAddRowBefore, "Table:::Insert Row Above", "Table:::Insert %d Rows Above", null);
107       add(PanmirrorCommands.TableDeleteRow, "Table:::Delete Row", "Delete %d Rows", null);
108       add(PanmirrorCommands.TableDeleteTable, "Delete Table");
109       add(PanmirrorCommands.TableNextCell, "Table:::Next Cell");
110       add(PanmirrorCommands.TablePreviousCell, "Table:::Previous Cell");
111       add(PanmirrorCommands.TableAlignColumnLeft, "Table Align Column:::Left", Roles.getMenuitemcheckboxRole());
112       add(PanmirrorCommands.TableAlignColumnRight, "Table Align Column:::Right", Roles.getMenuitemcheckboxRole());
113       add(PanmirrorCommands.TableAlignColumnCenter, "Table Align Column:::Center", Roles.getMenuitemcheckboxRole());
114       add(PanmirrorCommands.TableAlignColumnDefault, "Table Align Column:::Default", Roles.getMenuitemcheckboxRole());
115 
116       // insert
117       add(PanmirrorCommands.OmniInsert, "Any...", icons.OMNI);
118       add(PanmirrorCommands.Link, "Link...", icons.LINK);
119       add(PanmirrorCommands.RemoveLink, "Remove Link");
120       add(PanmirrorCommands.Image, "Image...", icons.IMAGE);
121       add(PanmirrorCommands.Footnote, "Footnote");
122       add(PanmirrorCommands.HorizontalRule, "Horizontal Rule");
123       add(PanmirrorCommands.ParagraphInsert, "Paragraph");
124       add(PanmirrorCommands.HTMLComment, "Comment", icons.COMMENT);
125       add(PanmirrorCommands.YamlMetadata, "YAML Block");
126       add(PanmirrorCommands.Shortcode, "Shortcode");
127       add(PanmirrorCommands.InsertDiv, "Div...");
128       add(PanmirrorCommands.InlineMath, "Inline Math");
129       add(PanmirrorCommands.DisplayMath, "Display Math");
130       add(PanmirrorCommands.DefinitionList, "Definition List");
131       add(PanmirrorCommands.DefinitionTerm, "Term");
132       add(PanmirrorCommands.DefinitionDescription, "Description");
133       add(PanmirrorCommands.Citation, "Citation...", icons.CITATION);
134       add(PanmirrorCommands.CrossReference, "Cross Reference");
135       add(PanmirrorCommands.InsertEmoji, "Insert Emoji...");
136       add(PanmirrorCommands.InsertSymbol, "Insert Unicode...");
137       add(PanmirrorCommands.EmDash, "Insert:::Em Dash (—)");
138       add(PanmirrorCommands.EnDash, "Insert:::En Dash (–)");
139       add(PanmirrorCommands.NonBreakingSpace, "Insert:::Non-Breaking Space");
140       add(PanmirrorCommands.HardLineBreak, "Insert:::Hard Line Break");
141 
142       // outline
143       add(PanmirrorCommands.GoToNextSection, "Go to Next Section");
144       add(PanmirrorCommands.GoToPreviousSection, "Go to Previous Section");
145       add(PanmirrorCommands.GoToNextChunk, "Go to Next Chunk");
146       add(PanmirrorCommands.GoToPreviousChunk, "Go to Previous Chunk");
147    }
148 
get(String id)149    public PanmirrorCommandUI get(String id)
150    {
151       return commandsUI_.get(id);
152    }
153 
exec(String id)154    public boolean exec(String id)
155    {
156       PanmirrorCommandUI command = get(id);
157       if (command != null)
158       {
159          if (command.isEnabled())
160          {
161             command.execute();
162          }
163          return true;
164       }
165       else
166       {
167          return false;
168       }
169    }
170 
171    @Override
getCommandPaletteItems()172    public List<CommandPaletteItem> getCommandPaletteItems()
173    {
174       List<CommandPaletteItem> items = new ArrayList<>();
175       for (PanmirrorCommandUI cmd: commandsUI_.values())
176       {
177          if (cmd != null && cmd.isVisible())
178          {
179             items.add(new PanmirrorCommandPaletteItem(cmd));
180          }
181       }
182       return items;
183    }
184 
185    @Override
getCommandPaletteItem(String id)186    public CommandPaletteItem getCommandPaletteItem(String id)
187    {
188       if (StringUtil.isNullOrEmpty(id))
189       {
190          return null;
191       }
192 
193       PanmirrorCommandUI cmd = commandsUI_.get(id);
194       if (cmd == null)
195       {
196          Debug.logWarning("Command palette requested unknown command from visual editor: '" + id + "'");
197       }
198 
199       return new PanmirrorCommandPaletteItem(cmd);
200    }
201 
202    @Override
getProviderScope()203    public String getProviderScope()
204    {
205       return CommandPalette.SCOPE_VISUAL_EDITOR;
206    }
207 
add(String id, String menuText)208    private void add(String id, String menuText)
209    {
210       add(id, menuText, Roles.getMenuitemRole());
211    }
212 
add(String id, String menuText, String pluralMenuText, String image)213    private void add(String id, String menuText, String pluralMenuText, String image)
214    {
215       add(id, menuText, pluralMenuText, Roles.getMenuitemRole(), image);
216    }
217 
add(String id, String menuText, String image)218    private void add(String id, String menuText, String image)
219    {
220       add(id, menuText, Roles.getMenuitemRole(), image);
221    }
222 
223 
add(String id, String menuText, MenuitemRole role)224    private void add(String id, String menuText, MenuitemRole role)
225    {
226       add(id, menuText, role, null);
227    }
228 
add(String id, String menuText, MenuitemRole role, String image)229    private void add(String id, String menuText, MenuitemRole role, String image)
230    {
231       add(id, menuText, null, role, image);
232    }
233 
add(String id, String menuText, String pluralMenuText, MenuitemRole role, String image)234    private void add(String id, String menuText, String pluralMenuText, MenuitemRole role, String image)
235    {
236       // lookup the underlying command
237       PanmirrorCommand command = null;
238       for (PanmirrorCommand cmd : commands_) {
239          if (cmd.id == id) {
240             command = cmd;
241             break;
242          }
243       }
244       // add it
245       commandsUI_.put(id, new PanmirrorCommandUI(command, menuText, pluralMenuText, role, image));
246    }
247 
248    private PanmirrorCommand[] commands_ = null;
249    private final HashMap<String,PanmirrorCommandUI> commandsUI_ = new HashMap<>();
250 }
251