Skip to content

Commit 7471aa9

Browse files
committed
Enhance MyTripToCanada with journey log feature, including message list and improved UI elements
Signed-off-by: makbn <[email protected]>
1 parent 29225f1 commit 7471aa9

File tree

1 file changed

+173
-62
lines changed

1 file changed

+173
-62
lines changed

jlmap-vaadin-demo/src/main/java/io/github/makbn/vaadin/demo/views/MyTripToCanada.java

Lines changed: 173 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import com.vaadin.flow.component.UI;
44
import com.vaadin.flow.component.button.Button;
5-
import com.vaadin.flow.component.button.ButtonVariant;
6-
import com.vaadin.flow.component.html.H2;
5+
import com.vaadin.flow.component.html.Anchor;
6+
import com.vaadin.flow.component.html.H3;
7+
import com.vaadin.flow.component.html.Span;
8+
import com.vaadin.flow.component.messages.MessageList;
9+
import com.vaadin.flow.component.messages.MessageListItem;
710
import com.vaadin.flow.component.notification.Notification;
8-
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
11+
import com.vaadin.flow.component.orderedlayout.FlexLayout;
912
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
1013
import com.vaadin.flow.router.Route;
1114
import io.github.makbn.jlmap.map.JLMapProvider;
@@ -14,6 +17,9 @@
1417
import org.slf4j.Logger;
1518
import org.slf4j.LoggerFactory;
1619

20+
import java.time.Instant;
21+
import java.util.ArrayList;
22+
import java.util.List;
1723
import java.util.concurrent.Executors;
1824
import java.util.concurrent.ScheduledExecutorService;
1925
import java.util.concurrent.TimeUnit;
@@ -89,14 +95,18 @@ public class MyTripToCanada extends VerticalLayout {
8995
private JLMapView mapView;
9096
private JLMarker currentMarker;
9197
private JLPolyline currentPath;
98+
private final List<MessageListItem> messages = new ArrayList<>();
99+
private MessageList messageList;
92100

93101
public MyTripToCanada() {
94-
setWidthFull();
95-
setHeight("100px");
102+
setSizeFull();
103+
setPadding(false);
104+
setSpacing(false);
96105

97-
98-
// Title
99-
H2 title = new H2("JL-Map Vaadin Demo");
106+
// Main content layout with map
107+
FlexLayout mainContent = new FlexLayout();
108+
mainContent.setSizeFull();
109+
mainContent.getStyle().set("position", "relative");
100110

101111
// Create the map view
102112
mapView = JLMapView.builder()
@@ -105,44 +115,122 @@ public MyTripToCanada() {
105115
.parameter(new JLMapOption.Parameter("initialZoom", "4"))
106116
.build())
107117
.startCoordinate(SARI)
108-
.showZoomController(true)
118+
.showZoomController(false)
109119
.build();
110-
mapView.getStyle().set("border-radius", "16px");
111-
112-
// Control panel
113-
HorizontalLayout controlPanel = new HorizontalLayout();
114-
controlPanel.setSpacing(true);
115-
controlPanel.setHeight("280px");
120+
mapView.setSizeFull();
121+
122+
// Create menu overlay (similar to HomeView)
123+
VerticalLayout menuWrapper = new VerticalLayout();
124+
menuWrapper.setClassName("jlmap-menu");
125+
126+
menuWrapper.setPadding(false);
127+
menuWrapper.setSpacing(false);
128+
menuWrapper.setWidth(null);
129+
menuWrapper.setMaxHeight("450px");
130+
menuWrapper.setMinWidth("280px");
131+
menuWrapper.setMaxWidth("350px");
132+
menuWrapper.setHeight(null);
133+
menuWrapper.getStyle()
134+
.set("position", "absolute")
135+
.set("bottom", "20px")
136+
.set("top", "80% !important")
137+
.set("left", "20px")
138+
.set("z-index", "1000")
139+
.set("background", "rgba(255, 255, 255, 0.95)")
140+
.set("border-radius", "8px")
141+
.set("box-shadow", "0 4px 12px rgba(0,0,0,0.15)")
142+
.set("padding", "16px");
143+
144+
// Menu content
145+
VerticalLayout menuContent = new VerticalLayout();
146+
menuContent.setPadding(false);
147+
menuContent.setSpacing(false);
148+
menuContent.setWidthFull();
116149

150+
// Title
151+
Span menuTitle = new Span("Java Leaflet: Vaadin");
152+
menuTitle.getStyle()
153+
.set("font-size", "1.1em")
154+
.set("font-weight", "600")
155+
.set("color", "var(--lumo-header-text-color)")
156+
.set("display", "block")
157+
.set("margin-bottom", "12px");
158+
159+
// Buttons
117160
Button startButton = new Button("✈️ Start Journey");
161+
startButton.setWidthFull();
162+
startButton.getStyle().set("margin-bottom", "8px");
118163
startButton.addClickListener(e -> {
119164
startButton.setEnabled(false);
165+
clearMessages();
120166
startJourney();
121167
});
122-
startButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
123168

124169
Button resetButton = new Button("🔄 Reset");
125-
resetButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
126-
170+
resetButton.setWidthFull();
127171
resetButton.addClickListener(e -> {
128172
resetJourney();
173+
clearMessages();
129174
startButton.setEnabled(true);
130175
});
131176

132-
controlPanel.add(title, startButton, resetButton);
133-
134-
add(controlPanel);
135-
addAndExpand(mapView);
177+
// GitHub footer
178+
Anchor githubLink = new Anchor("https://github.com/makbn/java_leaflet", "");
179+
githubLink.setTarget("_blank");
180+
githubLink.getStyle()
181+
.set("display", "flex")
182+
.set("align-items", "center")
183+
.set("justify-content", "center")
184+
.set("margin-top", "12px")
185+
.set("padding-top", "12px")
186+
.set("border-top", "1px solid var(--lumo-contrast-10pct)")
187+
.set("color", "var(--lumo-secondary-text-color)")
188+
.set("text-decoration", "none")
189+
.set("font-size", "0.875em");
190+
githubLink.getElement().setProperty("innerHTML",
191+
"<svg width='16' height='16' viewBox='0 0 16 16' fill='currentColor' style='margin-right: 6px;'><path d='M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.01.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.11.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.19 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z'/></svg>" +
192+
"<span>View on GitHub</span>");
193+
194+
menuContent.add(menuTitle, startButton, resetButton, githubLink);
195+
menuWrapper.add(menuContent);
196+
197+
// Message list panel
198+
VerticalLayout messagePanel = new VerticalLayout();
199+
messagePanel.setWidth("380px");
200+
messagePanel.getStyle()
201+
.set("border-left", "1px solid var(--lumo-contrast-10pct)");
202+
messagePanel.setPadding(false);
203+
messagePanel.setSpacing(false);
204+
205+
H3 messageTitle = new H3("📝 Journey Log");
206+
messageTitle.getStyle()
207+
.set("margin", "0")
208+
.set("padding", "var(--lumo-space-m)");
209+
210+
messageList = new MessageList();
211+
messageList.setItems(messages);
212+
213+
messagePanel.add(messageTitle, messageList);
214+
messagePanel.expand(messageList);
215+
216+
// Add components to main content
217+
mainContent.add(mapView, messagePanel);
218+
mainContent.expand(mapView);
219+
220+
// Add menu overlay on top of map
221+
mapView.getElement().appendChild(menuWrapper.getElement());
222+
223+
add(mainContent);
136224
}
137225

138226
private void startJourney() {
139227
log.info("Starting journey animation");
140228
resetJourney();
141229

142-
Notification.show("Starting journey from Sari, Iran...", 2000, Notification.Position.BOTTOM_CENTER);
230+
addMessage("🎬", "Journey begins! Buckle up for an adventure!", "#9C27B0");
143231
log.info("About to animate first segment: Sari to Tehran");
144232

145-
// Step 1: Car from Sari to Tehran (5 seconds)
233+
// Step 1: Car from Sari to Tehran (3 seconds)
146234
animateSegment(
147235
SARI,
148236
TEHRAN,
@@ -153,11 +241,12 @@ private void startJourney() {
153241
"Sari, Iran",
154242
"Tehran, Iran",
155243
() -> {
156-
// Step 2: Briefcase and passport (1 second)
157-
Notification.show("Arriving in Tehran - Getting ready to fly...", 2000, Notification.Position.BOTTOM_CENTER);
244+
addMessage("🚗", "Departed from beautiful Sari! Driving through scenic routes to Tehran...", "#FF5722");
245+
// Step 2: Briefcase and passport (1.5 seconds)
246+
addMessage("🏙️", "Arrived in Tehran! Time to pack my bags and grab my passport!", "#FF9800");
158247
showTransition(TEHRAN, BRIEFCASE_ICON, 1500, () -> {
159-
// Step 3: Airplane Tehran to Doha (3 seconds)
160-
Notification.show("Flying to Doha...", 2000, Notification.Position.BOTTOM_CENTER);
248+
// Step 3: Airplane Tehran to Doha (4 seconds)
249+
addMessage("✈️", "Taking off from Tehran! Soaring through the clouds to Doha...", "#2196F3");
161250
animateSegment(
162251
TEHRAN,
163252
DOHA,
@@ -168,11 +257,11 @@ private void startJourney() {
168257
"Tehran, Iran",
169258
"Doha, Qatar",
170259
() -> {
171-
// Step 4: Change airplane animation (same position)
172-
Notification.show("Transit in Doha...", 2000, Notification.Position.BOTTOM_CENTER);
260+
// Step 4: Transit in Doha (1.5 seconds)
261+
addMessage("🛬", "Landed in Doha! Quick layover for coffee and passport check ☕", "#00BCD4");
173262
showTransition(DOHA, PASSPORT_ICON, 1500, () -> {
174263
// Step 5: Airplane Doha to Montreal (5 seconds)
175-
Notification.show("Flying to Montreal, Canada...", 2000, Notification.Position.BOTTOM_CENTER);
264+
addMessage("🌍", "Crossing the Atlantic! Long flight ahead but Canada awaits! 🇨🇦", "#2196F3");
176265
animateSegment(
177266
DOHA,
178267
MONTREAL,
@@ -183,11 +272,11 @@ private void startJourney() {
183272
"Doha, Qatar",
184273
"Montreal, Canada",
185274
() -> {
186-
// Step 6: Paper document (1 second)
187-
Notification.show("Customs in Montreal...", 2000, Notification.Position.BOTTOM_CENTER);
275+
// Step 6: Customs in Montreal (1.5 seconds)
276+
addMessage("🍁", "Bonjour Montreal! Going through customs and immigration...", "#4CAF50");
188277
showTransition(MONTREAL, DOCUMENT_ICON, 1500, () -> {
189-
// Step 7: Red airplane Montreal to Calgary (4 seconds)
190-
Notification.show("Domestic flight to Calgary...", 2000, Notification.Position.BOTTOM_CENTER);
278+
// Step 7: Domestic flight to Calgary (4 seconds)
279+
addMessage("🛫", "Domestic flight time! Heading west to the Rockies!", "#E91E63");
191280
animateSegment(
192281
MONTREAL,
193282
CALGARY,
@@ -198,12 +287,14 @@ private void startJourney() {
198287
"Montreal, Canada",
199288
"Calgary, Canada",
200289
() -> {
201-
// Step 8: House at Calgary
202-
showTransition(CALGARY, HOUSE_ICON, 2000, () ->
203-
Notification.show("🎉 Welcome to Calgary, Canada! Journey Complete!",
204-
5000,
205-
Notification.Position.TOP_CENTER)
206-
);
290+
// Step 8: Arrived in Calgary
291+
addMessage("🏠", "FINALLY HOME in Calgary! What an amazing journey! 🎉", "#4CAF50");
292+
showTransition(CALGARY, HOUSE_ICON, 2000, () -> {
293+
addMessage("🎊", "Journey complete! Time to rest and enjoy the Rockies! 🏔️", "#9C27B0");
294+
Notification.show("🎉 Welcome to Calgary, Canada! Journey Complete!",
295+
5000,
296+
Notification.Position.TOP_CENTER);
297+
});
207298
}
208299
);
209300
});
@@ -221,6 +312,13 @@ private void animateSegment(JLLatLng start, JLLatLng end, JLIcon icon, String pa
221312
int duration, int zoomLevel, String departureName, String destinationName,
222313
Runnable onComplete) {
223314
log.info("Animating segment from {} to {} with icon {}", start, end, icon);
315+
// Fly to show the route
316+
JLLatLng midPoint = new JLLatLng(
317+
(start.getLat() + end.getLat()) / 2,
318+
(start.getLng() + end.getLng()) / 2
319+
);
320+
log.info("Flying to midpoint: {}", midPoint);
321+
mapView.getControlLayer().flyTo(midPoint, zoomLevel);
224322

225323
// Add popup at departure
226324
JLPopup departurePopup = mapView.getUiLayer().addPopup(start,
@@ -236,26 +334,6 @@ private void animateSegment(JLLatLng start, JLLatLng end, JLIcon icon, String pa
236334
JLLatLng[] pathPoints = createCurvedPath(start, end, 300);
237335
log.info("Created path with {} points", pathPoints.length);
238336

239-
currentPath = mapView.getVectorLayer().addPolyline(
240-
pathPoints,
241-
JLOptions.DEFAULT.toBuilder()
242-
.color(JLColor.fromHex(pathColor))
243-
.fillColor(JLColor.fromHex("#00FFFFFF"))
244-
.color(JLColor.fromHex("#00FFFFFF"))
245-
.fill(false)
246-
.weight(4)
247-
.opacity(0.7)
248-
.build()
249-
);
250-
log.info("Added polyline to map");
251-
252-
// Fly to show the route
253-
JLLatLng midPoint = new JLLatLng(
254-
(start.getLat() + end.getLat()) / 2,
255-
(start.getLng() + end.getLng()) / 2
256-
);
257-
log.info("Flying to midpoint: {}", midPoint);
258-
mapView.getControlLayer().flyTo(midPoint, zoomLevel);
259337

260338
// Add popup at destination
261339
JLPopup destinationPopup = mapView.getUiLayer().addPopup(end,
@@ -299,6 +377,21 @@ private void animateMarkerAlongPath(JLIcon icon, JLLatLng[] path, int duration,
299377

300378
executor.scheduleAtFixedRate(() -> {
301379
int step = currentStep.getAndIncrement();
380+
if (step == 1) {
381+
ui.access(() -> {
382+
currentPath = mapView.getVectorLayer().addPolyline(
383+
path,
384+
JLOptions.DEFAULT.toBuilder()
385+
.fillColor(JLColor.fromHex("#00FFFFFF"))
386+
.color(JLColor.fromHex("#00FFFFFF"))
387+
.fill(false)
388+
.weight(4)
389+
.opacity(0.7)
390+
.build()
391+
);
392+
log.info("Added polyline to map");
393+
});
394+
}
302395

303396
if (step <= totalSteps) {
304397
// Calculate which point in the path to use
@@ -323,7 +416,7 @@ private void animateMarkerAlongPath(JLIcon icon, JLLatLng[] path, int duration,
323416
ui.access(onComplete::run);
324417
}
325418
}
326-
}, 0, delayPerStep, TimeUnit.MILLISECONDS);
419+
}, 1000, delayPerStep, TimeUnit.MILLISECONDS);
327420
}
328421

329422
private void showTransition(JLLatLng position, JLIcon icon, int duration, Runnable onComplete) {
@@ -391,4 +484,22 @@ private void resetJourney() {
391484
// Reset view to starting position
392485
mapView.getControlLayer().flyTo(SARI, 4);
393486
}
487+
488+
private void addMessage(String icon, String message, String color) {
489+
UI.getCurrent().access(() -> {
490+
MessageListItem item = new MessageListItem(
491+
icon + " " + message,
492+
Instant.now(),
493+
"Journey Bot"
494+
);
495+
496+
messages.add(item);
497+
messageList.setItems(messages);
498+
});
499+
}
500+
501+
private void clearMessages() {
502+
messages.clear();
503+
messageList.setItems(messages);
504+
}
394505
}

0 commit comments

Comments
 (0)