22
33import com .ibm .icu .impl .CalendarAstronomer ;
44import com .vaadin .event .LayoutEvents ;
5+ import com .vaadin .navigator .Navigator ;
56import com .vaadin .server .*;
67import com .vaadin .ui .*;
78
2223@ Theme ("demo" )
2324@ Title ("GridStack Add-on Demo" )
2425@ SuppressWarnings ("serial" )
25- public class DemoUI extends UI
26- {
26+ public class DemoUI extends UI {
2727
28- private GridStackLayout gridStack ;
28+ private Navigator navigator ;
2929
30- private AtomicInteger eventCounter = new AtomicInteger (0 );
31- private TextArea eventConsole = new TextArea ();
32-
33- private Random rand = new Random (0xDEADBEEF );
34-
35- private Component locked ;
36-
37- // This value can be used as x and y when client side can pick the best slot
38- private final static int CLIENT_SELECTS = GridStackLayout .CLIENT_SIDE_SELECTS ;
3930
4031 @ WebServlet (value = "/*" , asyncSupported = true )
4132 @ VaadinServletConfiguration (productionMode = false , ui = DemoUI .class ,
@@ -46,270 +37,9 @@ public static class Servlet extends VaadinServlet {
4637 @ Override
4738 protected void init (VaadinRequest request ) {
4839
49- // By default gridstack has three columns (and calls that only work before client side attachment)
50- gridStack = new GridStackLayout (8 )
51- .setVerticalMargin (12 )
52- .setMinWidth (300 )
53- .setAnimate (true );
54-
55- // See styles.scss of this demo project how to handle columns sizes on CSS size
56- gridStack .addStyleName ("eight-column-grid-stack" );
57-
58- // One cell height is set to 80 pixels
59- gridStack .setCellHeight (80 );
60-
61- // Show it in the middle of the screen
62- final VerticalLayout layout = new VerticalLayout ();
63- layout .setStyleName ("demoContentLayout" );
64- layout .setSizeFull ();
65- layout .setMargin (true );
66- layout .setSpacing (true );
67- setContent (layout );
68-
69- layout .addComponent (createToolbar ());
70-
71- Panel gridStackWrapper = new Panel ();
72- gridStackWrapper .addStyleName ("gridstack-wrapper" );
73- gridStackWrapper .setSizeFull ();
74- layout .addComponent (gridStackWrapper );
75- layout .setExpandRatio (gridStackWrapper , 1f );
76-
77- layout .addComponent (new Link (
78- "This project is based on gridstack.js JavaScript library, written by Pavel Reznikov" ,
79- new ExternalResource ("https://github.com/troolee/gridstack.js" )));
80-
81- // ----
82-
83- gridStackWrapper .setContent (gridStack );
84- gridStack .setSizeFull ();
85-
86- gridStack .addComponent (new Label ("This child can be dragged without handle. Please use separate handle "
87- + "(default mode) when you child component is, or has, an active Vaadin component." ), 0 , 0 , 1 , 3 , false );
88-
89- locked = new Label ("This component can be \" locked\" (moving other children will not move this)" );
90- gridStack .addComponent (locked , 1 , 0 , 3 , 1 );
91-
92- gridStack .addComponent (createForm (), 0 , 5 , 2 , 3 , false );
93- gridStack .addComponent (createConsole (), 0 , 3 , 4 , 2 );
94-
95- Component image = createImage ();
96- gridStack .addComponent (image , 2 , 1 , 3 , 2 );
97- gridStack .setWrapperScrolling (image , false );
98- gridStack .setComponentSizeLimits (image , 3 , null , 2 , null );
99-
100- gridStack .addGridStackMoveListener (events -> {
101- final int eventId = eventCounter .getAndIncrement ();
102- events .stream ().forEach (event -> {
103- addEvent ("event #" + eventId + ": Moved from " + event .getOld ().toString () + " to "
104- + event .getNew ().toString ());
105- });
106- });
107- }
108-
109- private Component createToolbar () {
110- HorizontalLayout toolbar = new HorizontalLayout ();
111- toolbar .setSpacing (true );
112-
113- toolbar .addComponent (new Label ("GridStack Demo" ));
114-
115- toolbar .addComponent (createButton (FontAwesome .PLUS , "Add component" , e -> {
116- int index = gridStack .getComponentCount ();
117- final CssLayout layout = new CssLayout ();
118- layout .addStyleName ("hep-layout" );
119- layout .addComponent (new Label ("Hep #" + index ));
120- Button button = new Button ("Remove this" , ce -> {
121- gridStack .removeComponent (layout );
122- });
123- button .addStyleName (ValoTheme .BUTTON_SMALL );
124- button .addStyleName (ValoTheme .BUTTON_BORDERLESS_COLORED );
125- layout .addComponent (button );
126- gridStack .addComponent (layout , CLIENT_SELECTS , CLIENT_SELECTS , 1 + rand .nextInt (3 ), 1 );
127- }));
128-
129- toolbar .addComponent (createButton (FontAwesome .MINUS , "Remove component" , e -> {
130- int index = rand .nextInt (gridStack .getComponentCount ());
131- Iterator <Component > iter = gridStack .iterator ();
132- for (int i = 0 ; i < index ; ++i ) {
133- iter .next ();
134- }
135- gridStack .removeComponent (iter .next ());
136- }));
137-
138- CheckBox layoutClicks = new CheckBox ("Layout clicks" );
139- layoutClicks .setDescription ("Adds layout click listener to GridStackLayout" );
140- layoutClicks .addValueChangeListener (e -> {
141- if ((Boolean )e .getProperty ().getValue ()) {
142- gridStack .addLayoutClickListener (layoutClickListener );
143- } else {
144- gridStack .removeLayoutClickListener (layoutClickListener );
145- }
146- });
147- toolbar .addComponent (layoutClicks );
148-
149- toolbar .addComponent (createButton (FontAwesome .ARROWS , "Move random child to new location" ,
150- e -> moveRandomChildToAnotherFreePosition ()));
151-
152- toolbar .addComponent (createButton (FontAwesome .RANDOM , "Reorder all items to new order" , e -> reorderAll ()));
153-
154- CheckBox staticGrid = new CheckBox ("Static" );
155- staticGrid .setDescription ("If static, dragging and resizing are not allowed by user" );
156- staticGrid .addValueChangeListener (e -> {
157- gridStack .setStaticGrid ((Boolean )e .getProperty ().getValue ());
158- });
159- toolbar .addComponent (staticGrid );
160-
161- CheckBox lockItem = new CheckBox ("Lock child" );
162- lockItem .setDescription ("Define if item with text \" can be locked\" is locked or not" );
163- lockItem .addValueChangeListener (e -> {
164- gridStack .setComponentLocked (locked , (Boolean )e .getProperty ().getValue ());
165- });
166- toolbar .addComponent (lockItem );
167-
168- return toolbar ;
169- }
170-
171- private void addEvent (String message ) {
172- eventConsole .setValue (message + "\r \n " + eventConsole .getValue ());
173- }
174-
175- private Button createButton (Resource icon , String caption , String description , Button .ClickListener listener ) {
176- Button button = new Button ();
177- button .addStyleName (ValoTheme .BUTTON_SMALL );
178- button .addClickListener (listener );
179- if (icon != null ) {
180- button .setIcon (icon );
181- }
182- if (caption != null ) {
183- button .setCaption (caption );
184- }
185- if (description != null ) {
186- button .setDescription (description );
187- }
188- return button ;
189- }
190-
191- private Button createButton (Resource icon , String description , Button .ClickListener listener ) {
192- return createButton (icon , null , description , listener );
193- }
194-
195- private Button createButton (String caption , String description , Button .ClickListener listener ) {
196- return createButton (null , caption , description , listener );
197- }
198-
199- private Component createForm () {
200- VerticalLayout layout = new VerticalLayout ();
201- layout .setMargin (true );
202- layout .setSpacing (true );
203- layout .setWidth (100 , Unit .PERCENTAGE );
204- TextField username = new TextField ();
205- username .setWidth (100 , Unit .PERCENTAGE );
206- username .addStyleName (ValoTheme .TEXTFIELD_SMALL );
207- username .setCaption ("Username:" );
208- layout .addComponent (username );
209- PasswordField password = new PasswordField ();
210- password .setWidth (100 , Unit .PERCENTAGE );
211- password .addStyleName (ValoTheme .TEXTFIELD_SMALL );
212- password .setCaption ("Password:" );
213- layout .addComponent (password );
214- Button login = new GridStackButton ("Login" , e -> Notification .show ("Logged in?" ));
215- login .addStyleName (ValoTheme .BUTTON_SMALL );
216- layout .addComponent (login );
217- layout .setComponentAlignment (login , Alignment .BOTTOM_RIGHT );
218- Label info = new Label ("Also this child can be dragged without handle. GridStackButton used to resolve event "
219- + "issues caused by normal Button." );
220- info .addStyleName ("info-text" );
221- layout .addComponent (info );
222- return layout ;
223- }
224-
225- private Component createConsole () {
226- VerticalLayout layout = new VerticalLayout ();
227- layout .addStyleName ("eventconsole-wrapper" );
228- layout .setSizeFull ();
229- eventConsole .setCaption ("Event console" );
230- eventConsole .setSizeFull ();
231- eventConsole .setValue ("Events will be written here." );
232- layout .addComponent (eventConsole );
233- return layout ;
234- }
235-
236- private Component createImage () {
237- CssLayout wrapper = new CssLayout ();
238- wrapper .setSizeFull ();
239- wrapper .addStyleName ("image-wrapper" );
240-
241- Image image = new Image (null , new ThemeResource ("images/rude.jpg" ));
242- wrapper .addComponent (image );
243- return wrapper ;
244- }
245-
246- LayoutEvents .LayoutClickListener layoutClickListener = e -> {
247- boolean clickedAtChild = e .getChildComponent () != null ;
248- StringBuilder sb = new StringBuilder ();
249- sb .append ("User clicked at [" )
250- .append (e .getClientX ())
251- .append ("," )
252- .append (e .getClientY ())
253- .append ("] " );
254- sb .append (clickedAtChild ? "at child" : "at background." );
255-
256- if (clickedAtChild ) {
257- sb .append (": " );
258- sb .append (gridStack .getCoordinates (e .getChildComponent ()).toString ());
259- }
260-
261- addEvent (sb .toString ());
262- };
263-
264- private void reorderAll () {
265- addEvent ("Reorder all components..." );
266-
267- List <Component > children = new ArrayList <>();
268- gridStack .iterator ().forEachRemaining (child -> {
269- //Move away temporary
270- gridStack .moveComponent (child , 100 , 100 );
271- children .add (child );
272- });
273-
274- Collections .shuffle (children , rand );
275- children .forEach (child -> moveChildToAnotherFreePosition (child ));
276- }
277-
278- private void moveRandomChildToAnotherFreePosition () {
279- List <Component > children = new ArrayList <>();
280- gridStack .iterator ().forEachRemaining (child -> children .add (child ));
281- if (!children .isEmpty ()) {
282- addEvent ("Move random child to new position..." );
283- Collections .shuffle (children , rand );
284- moveChildToAnotherFreePosition (children .get (0 ));
285- }
286- }
287-
288- // Just ugly hack to find suitable slot on server side. This will onlu work if server side has actual location of
289- // child component
290- private void moveChildToAnotherFreePosition (Component child ) {
291- GridStackCoordinates oldCoords = gridStack .getCoordinates (child );
292- int width = oldCoords .getWidth ();
293- int height = oldCoords .getHeight ();
294-
295- final int columnsTested = 8 ;
296- final int rowsTested = 8 ;
297- for (int slotIndex = 0 ; slotIndex < columnsTested * rowsTested ; ++slotIndex ) {
298- int x = slotIndex % columnsTested ;
299- int y = slotIndex / columnsTested ;
300-
301- if (oldCoords .isXAndY (x , y )) {
302- continue ;
303- }
304-
305- if (gridStack .isAreaEmpty (x , y , width , height )) {
306- addEvent ("Moving child server side to new position x:" + x + " y:" + y + "..." );
307- gridStack .moveComponent (child , x , y );
308- return ;
309- }
310- }
311-
312- addEvent ("!!! Failed to find new available position for child" );
40+ navigator = new Navigator (this , this );
41+ navigator .addView (TestView .VIEW_NAME , TestView .class );
42+ navigator .addView (SplitView .VIEW_NAME , SplitView .class );
31343 }
31444
31545}
0 commit comments