]> git.argeo.org Git - lgpl/argeo-commons.git/blob - acr/SwtTabbedArea.java
Prepare next development cycle
[lgpl/argeo-commons.git] / acr / SwtTabbedArea.java
1 package org.argeo.cms.swt.acr;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.argeo.api.acr.Content;
7 import org.argeo.api.acr.spi.ProvidedContent;
8 import org.argeo.cms.swt.CmsSwtUtils;
9 import org.argeo.cms.swt.Selected;
10 import org.eclipse.swt.SWT;
11 import org.eclipse.swt.custom.StackLayout;
12 import org.eclipse.swt.graphics.Image;
13 import org.eclipse.swt.layout.GridData;
14 import org.eclipse.swt.layout.GridLayout;
15 import org.eclipse.swt.widgets.Button;
16 import org.eclipse.swt.widgets.Composite;
17 import org.eclipse.swt.widgets.Control;
18 import org.eclipse.swt.widgets.Label;
19 import org.eclipse.swt.widgets.ToolBar;
20 import org.eclipse.swt.widgets.ToolItem;
21
22 /** Manages {@link SwtSection} in a tab-like structure. */
23 public class SwtTabbedArea extends Composite {
24 private static final long serialVersionUID = 8659669229482033444L;
25
26 private Composite headers;
27 private Composite body;
28
29 private List<SwtSection> sections = new ArrayList<>();
30
31 private ProvidedContent previousNode;
32 private SwtUiProvider previousUiProvider;
33 private SwtUiProvider currentUiProvider;
34
35 private String tabStyle;
36 private String tabSelectedStyle;
37 private String bodyStyle;
38 private Image closeIcon;
39
40 private StackLayout stackLayout;
41
42 private boolean singleTab = false;
43
44 public SwtTabbedArea(Composite parent, int style) {
45 super(parent, SWT.NONE);
46 CmsSwtUtils.style(parent, bodyStyle);
47
48 setLayout(CmsSwtUtils.noSpaceGridLayout());
49
50 // TODO manage tabs at bottom or sides
51 headers = new Composite(this, SWT.NONE);
52 headers.setLayoutData(CmsSwtUtils.fillWidth());
53 body = new Composite(this, SWT.NONE);
54 body.setLayoutData(CmsSwtUtils.fillAll());
55 // body.setLayout(new FormLayout());
56 stackLayout = new StackLayout();
57 body.setLayout(stackLayout);
58 emptyState();
59 }
60
61 protected void refreshTabHeaders() {
62 int tabCount = sections.size() > 0 ? sections.size() : 1;
63 for (Control tab : headers.getChildren())
64 tab.dispose();
65
66 headers.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(tabCount, true)));
67
68 if (sections.size() == 0) {
69 Composite emptyHeader = new Composite(headers, SWT.NONE);
70 emptyHeader.setLayoutData(CmsSwtUtils.fillAll());
71 emptyHeader.setLayout(new GridLayout());
72 Label lbl = new Label(emptyHeader, SWT.NONE);
73 lbl.setText("");
74 lbl.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false));
75
76 }
77
78 SwtSection currentSection = getCurrentSection();
79 for (SwtSection section : sections) {
80 boolean selected = section == currentSection;
81 Composite sectionHeader = section.createHeader(headers);
82 CmsSwtUtils.style(sectionHeader, selected ? tabSelectedStyle : tabStyle);
83 int headerColumns = singleTab ? 1 : 2;
84 sectionHeader.setLayout(new GridLayout(headerColumns, false));
85 sectionHeader.setLayout(CmsSwtUtils.noSpaceGridLayout(headerColumns));
86 Button title = new Button(sectionHeader, SWT.FLAT);
87 CmsSwtUtils.style(title, selected ? tabSelectedStyle : tabStyle);
88 title.setLayoutData(CmsSwtUtils.fillWidth());
89 title.addSelectionListener((Selected) (e) -> showTab(tabIndex(section.getNode())));
90 Content node = section.getContent();
91
92 // FIXME find a standard way to display titles
93 String titleStr = node.getName().getLocalPart();
94
95 // TODO internationalize
96 title.setText(titleStr);
97 if (!singleTab) {
98 ToolBar toolBar = new ToolBar(sectionHeader, SWT.NONE);
99 ToolItem closeItem = new ToolItem(toolBar, SWT.FLAT);
100 if (closeIcon != null)
101 closeItem.setImage(closeIcon);
102 else
103 closeItem.setText("X");
104 CmsSwtUtils.style(closeItem, selected ? tabSelectedStyle : tabStyle);
105 closeItem.addSelectionListener((Selected) (e) -> closeTab(section));
106 }
107 }
108
109 }
110
111 public void view(SwtUiProvider uiProvider, Content context) {
112 if (body.isDisposed())
113 return;
114 int index = tabIndex(context);
115 if (index >= 0) {
116 showTab(index);
117 previousNode = (ProvidedContent) context;
118 previousUiProvider = uiProvider;
119 return;
120 }
121 SwtSection section = (SwtSection) body.getChildren()[0];
122 previousNode = (ProvidedContent) section.getNode();
123 if (previousNode == null) {// empty state
124 previousNode = (ProvidedContent) context;
125 previousUiProvider = uiProvider;
126 } else {
127 previousUiProvider = currentUiProvider;
128 }
129 currentUiProvider = uiProvider;
130 section.setContent(context);
131 // section.setLayoutData(CmsUiUtils.coverAll());
132 build(section, uiProvider, context);
133 if (sections.size() == 0)
134 sections.add(section);
135 refreshTabHeaders();
136 index = tabIndex(context);
137 showTab(index);
138 layout(true, true);
139 }
140
141 public void open(SwtUiProvider uiProvider, Content context) {
142 if (singleTab)
143 throw new UnsupportedOperationException("Open is not supported in single tab mode.");
144
145 if (previousNode != null
146 && previousNode.getSessionLocalId().equals(((ProvidedContent) context).getSessionLocalId())) {
147 // does nothing
148 return;
149 }
150 if (sections.size() == 0)
151 CmsSwtUtils.clear(body);
152 SwtSection currentSection = getCurrentSection();
153 int currentIndex = sections.indexOf(currentSection);
154 SwtSection previousSection = new SwtSection(body, SWT.NONE, context);
155 build(previousSection, previousUiProvider, previousNode);
156 // previousSection.setLayoutData(CmsUiUtils.coverAll());
157 int newIndex = currentIndex + 1;
158 sections.add(currentIndex, previousSection);
159 // sections.add(newIndex, previousSection);
160 showTab(newIndex);
161 refreshTabHeaders();
162 layout(true, true);
163 }
164
165 public void showTab(int index) {
166 SwtSection sectionToShow = sections.get(index);
167 // sectionToShow.moveAbove(null);
168 stackLayout.topControl = sectionToShow;
169 refreshTabHeaders();
170 layout(true, true);
171 }
172
173 protected void build(SwtSection section, SwtUiProvider uiProvider, Content context) {
174 for (Control child : section.getChildren())
175 child.dispose();
176 CmsSwtUtils.style(section, bodyStyle);
177 section.setContent(context);
178 uiProvider.createUiPart(section, context);
179
180 }
181
182 private int tabIndex(Content context) {
183 for (int i = 0; i < sections.size(); i++) {
184 SwtSection section = sections.get(i);
185 if (section.getSessionLocalId().equals(((ProvidedContent) context).getSessionLocalId()))
186 return i;
187 }
188 return -1;
189 }
190
191 public void closeTab(SwtSection section) {
192 int currentIndex = sections.indexOf(section);
193 int nextIndex = currentIndex == 0 ? 0 : currentIndex - 1;
194 sections.remove(section);
195 section.dispose();
196 if (sections.size() == 0) {
197 emptyState();
198 refreshTabHeaders();
199 layout(true, true);
200 return;
201 }
202 refreshTabHeaders();
203 showTab(nextIndex);
204 }
205
206 public void closeAllTabs() {
207 for (SwtSection section : sections) {
208 section.dispose();
209 }
210 sections.clear();
211 emptyState();
212 refreshTabHeaders();
213 layout(true, true);
214 }
215
216 protected void emptyState() {
217 new SwtSection(body, SWT.NONE, null);
218 refreshTabHeaders();
219 }
220
221 public Composite getCurrent() {
222 return getCurrentSection();
223 }
224
225 protected SwtSection getCurrentSection() {
226 return (SwtSection) stackLayout.topControl;
227 }
228
229 public Content getCurrentContext() {
230 SwtSection section = getCurrentSection();
231 if (section != null) {
232 return section.getNode();
233 } else {
234 return null;
235 }
236 }
237
238 public void setTabStyle(String tabStyle) {
239 this.tabStyle = tabStyle;
240 }
241
242 public void setTabSelectedStyle(String tabSelectedStyle) {
243 this.tabSelectedStyle = tabSelectedStyle;
244 }
245
246 public void setBodyStyle(String bodyStyle) {
247 this.bodyStyle = bodyStyle;
248 }
249
250 public void setCloseIcon(Image closeIcon) {
251 this.closeIcon = closeIcon;
252 }
253
254 public void setSingleTab(boolean singleTab) {
255 this.singleTab = singleTab;
256 }
257
258 }