1 /*
2  * PanmirrorToolbar.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 
20 import org.rstudio.core.client.widget.HasFindReplace;
21 import org.rstudio.core.client.widget.SecondaryToolbar;
22 import org.rstudio.core.client.widget.ToolbarButton;
23 import org.rstudio.core.client.widget.ToolbarMenuButton;
24 import org.rstudio.studio.client.workbench.views.source.editors.text.findreplace.FindReplaceBar;
25 
26 import com.google.gwt.dom.client.Style.Unit;
27 import com.google.gwt.event.dom.client.ClickEvent;
28 import com.google.gwt.event.dom.client.ClickHandler;
29 import com.google.gwt.user.client.ui.HorizontalPanel;
30 import com.google.gwt.user.client.ui.RequiresResize;
31 import com.google.gwt.user.client.ui.Widget;
32 
33 
34 public class PanmirrorToolbar extends SecondaryToolbar implements RequiresResize
35 {
PanmirrorToolbar()36    public PanmirrorToolbar()
37    {
38       super(false, "Panmirror Editor Toolbar");
39       getElement().getStyle().setHeight(getHeight(), Unit.PX);
40    }
41 
42    @Override
getHeight()43    public int getHeight()
44    {
45       return 23;
46    }
47 
init(PanmirrorToolbarCommands commands, PanmirrorMenus menus, HasFindReplace findReplace)48    public void init(PanmirrorToolbarCommands commands, PanmirrorMenus menus, HasFindReplace findReplace)
49    {
50 
51       commands_ = commands;
52       menus_ = menus;
53       commandObjects_.clear();
54       removeAllWidgets();
55 
56       PanmirrorToolbarRadioMenu blockMenu = createBlockMenu();
57       addLeftTextMenu(addRadioMenu(blockMenu));
58 
59       addLeftSeparator();
60 
61       formatWidgets_ = addWidgetGroup(
62          addLeftButton(PanmirrorCommands.Strong),
63          addLeftButton(PanmirrorCommands.Em),
64          addLeftButton(PanmirrorCommands.Underline),
65          addLeftButton(PanmirrorCommands.Code),
66          addLeftSeparator(),
67          addLeftButton(PanmirrorCommands.ClearFormatting),
68          addLeftSeparator()
69       );
70 
71       blockWidgets_ = addWidgetGroup(
72          addLeftButton(PanmirrorCommands.BulletList),
73          addLeftButton(PanmirrorCommands.OrderedList),
74          addLeftButton(PanmirrorCommands.Blockquote),
75          addLeftSeparator()
76       );
77 
78       insertWidgets_ = addWidgetGroup(
79          addLeftButton(PanmirrorCommands.Link),
80          addLeftButton(PanmirrorCommands.Citation),
81          addLeftSeparator(),
82          addLeftButton(PanmirrorCommands.Image),
83          addLeftSeparator()
84       );
85 
86 
87       PanmirrorToolbarMenu formatMenu = new PanmirrorToolbarMenu(commands_, menus_.format);
88       addLeftTextMenu(new ToolbarMenuButton("Format", "Format", null, formatMenu, false));
89 
90       addLeftSeparator();
91 
92       PanmirrorToolbarMenu insertMenu = new PanmirrorToolbarMenu(commands_, menus_.insert);
93       addLeftTextMenu(new ToolbarMenuButton("Insert", "Insert", null, insertMenu, false));
94 
95       if (haveAnyOf(PanmirrorCommands.TableInsertTable))
96       {
97          addLeftSeparator();
98          PanmirrorToolbarMenu tableMenu = new PanmirrorToolbarMenu(commands_, menus_.table);
99          addLeftTextMenu(new ToolbarMenuButton("Table", "Table", null, tableMenu, false));
100       }
101 
102       if (findReplace != null)
103       {
104          addLeftSeparator();
105          findReplaceButton_ = new ToolbarButton(
106             ToolbarButton.NoText,
107             "Find/Replace",
108             FindReplaceBar.getFindIcon(),
109             new ClickHandler() {
110                public void onClick(ClickEvent event)
111                {
112                   boolean show = !findReplace.isFindReplaceShowing();
113                   findReplace.showFindReplace(show);
114                }
115             });
116          addLeftWidget(findReplaceButton_);
117       }
118    }
119 
120 
sync(boolean images)121    public void sync(boolean images)
122    {
123       commandObjects_.forEach((object) -> object.sync(images));
124       invalidateSeparators();
125       onResize();
126    }
127 
setFindReplaceLatched(boolean latched)128    public void setFindReplaceLatched(boolean latched)
129    {
130       if (findReplaceButton_ != null)
131       {
132          findReplaceButton_.setLeftImage(latched ?
133             FindReplaceBar.getFindLatchedIcon() :
134             FindReplaceBar.getFindIcon()
135          );
136       }
137    }
138 
139    @Override
addLeftSeparator()140    public Widget addLeftSeparator()
141    {
142       Widget separator = super.addLeftSeparator();
143       separator.addStyleName(RES.styles().toolbarSeparator());
144       return separator;
145    }
146 
147    @Override
onResize()148    public void onResize()
149    {
150       int width = getOffsetWidth();
151       if (width == 0)
152          return;
153 
154       formatWidgets_.setVisible(width > 475);
155       blockWidgets_.setVisible(width > 555);
156       insertWidgets_.setVisible(width > 610);
157 
158    }
159 
160 
createBlockMenu()161    private PanmirrorToolbarRadioMenu createBlockMenu()
162    {
163       PanmirrorToolbarRadioMenu blockMenu = new PanmirrorToolbarRadioMenu("Normal", "Block Format", commands_);
164       blockMenu.addCommand(PanmirrorCommands.Paragraph);
165       blockMenu.addSeparator();
166       blockMenu.addCommand(PanmirrorCommands.Heading1);
167       blockMenu.addCommand(PanmirrorCommands.Heading2);
168       blockMenu.addCommand(PanmirrorCommands.Heading3);
169       blockMenu.addCommand(PanmirrorCommands.Heading4);
170       blockMenu.addCommand(PanmirrorCommands.Heading5);
171       blockMenu.addCommand(PanmirrorCommands.Heading6);
172       blockMenu.addSeparator();
173       blockMenu.addCommand(PanmirrorCommands.CodeBlock);
174       return blockMenu;
175    }
176 
177 
178 
haveAnyOf(String...ids)179    private boolean haveAnyOf(String...ids)
180    {
181       for (String id : ids)
182       {
183          if (commands_.get(id).isVisible())
184             return true;
185       }
186       return false;
187    }
188 
189 
addLeftButton(String id)190    private Widget addLeftButton(String id)
191    {
192       return addLeftWidget(addButton(id));
193    }
194 
addLeftTextMenu(ToolbarMenuButton menuButton)195    private void addLeftTextMenu(ToolbarMenuButton menuButton)
196    {
197       addLeftWidget(menuButton);
198       menuButton.addStyleName(RES.styles().toolbarTextMenuButton());
199    }
200 
addRadioMenu(PanmirrorToolbarRadioMenu menu)201    private PanmirrorToolbarRadioMenu addRadioMenu(PanmirrorToolbarRadioMenu menu)
202    {
203       commandObjects_.add(menu);
204       return menu;
205    }
206 
addButton(String id)207    private PanmirrorCommandButton addButton(String id)
208    {
209       PanmirrorCommandButton button = new PanmirrorCommandButton(commands_.get(id));
210       commandObjects_.add(button);
211       return button;
212    }
213 
addWidgetGroup(Widget...widgets)214    private HorizontalPanel addWidgetGroup(Widget...widgets)
215    {
216       HorizontalPanel group = new HorizontalPanel();
217       for (Widget widget : widgets)
218          group.add(widget);
219       addLeftWidget(group);
220       return group;
221    }
222 
223    private static final PanmirrorToolbarResources RES = PanmirrorToolbarResources.INSTANCE;
224 
225    private HorizontalPanel formatWidgets_ = null;
226    private HorizontalPanel insertWidgets_ = null;
227    private HorizontalPanel blockWidgets_ = null;
228 
229    private ToolbarButton findReplaceButton_ = null;
230 
231    private PanmirrorToolbarCommands commands_ = null;
232    private PanmirrorMenus menus_ = null;
233    private ArrayList<PanmirrorCommandUIObject> commandObjects_ = new ArrayList<>();
234 }
235