DEV Community

Cover image for GSoC Progress (Weeks 1–4) at MIT App Inventor — Building a Responsive GWT Interface
divyanshu_Kumar
divyanshu_Kumar

Posted on

2 1 1 1

GSoC Progress (Weeks 1–4) at MIT App Inventor — Building a Responsive GWT Interface

So far, GSoC has been an incredibly rewarding journey. Building mobile‑friendly UIs with GWT UiBinder and Java has pushed me to solve real‑world challenges—and every obstacle has taught me something new. In this post, I’ll share my progress through Week 4 and the key lessons I’ve learned along the way.

Week 1: Planning & Mentor Review

During the first week, I dove into the existing codebase to understand its structure and began envisioning how the mobile UI components would connect. I sketched out my implementation plan and discussed it in detail with my mentor, outlining the key integration points and data flows. Although this period coincided with my semester exams (so I couldn’t code as much as I’d hoped), I came away with a clear roadmap for building and wiring up the mobile interface.

Week 2: Building a Standalone Mobile UI with GWT & UiBinder

This week, I began building a standalone mobile UI module from the ground up instead of retrofitting the existing desktop code with media queries—an approach that often leads to cluttered styles and unintended breakages. By leveraging GWT and UiBinder (the same stack behind MIT App Inventor), we write type‑safe Java that compiles to optimised JavaScript, enjoy robust IDE support and compile‑time checks, and define our layouts declaratively in XML for a clean separation of structure and behaviour. This lets us reuse the desktop’s core business logic without touching its styles, avoid the cross‑browser quirks common in pure JavaScript frameworks, and benefit from GWT‑RPC’s efficient client–server communication and strong unit‑testing tools. In doing so, we achieve a maintainable, scalable codebase with clear separation of concerns—desktop versus mobile—and a mentor‑approved foundation for a robust mobile interface.

Challenges

Breakpoint-Driven Desktop‑to‑Mobile Interface Swap

In our GWT app, we define a numeric breakpoint—say, 768px—that separates desktop from mobile. On initial load, we call

int width = Window.getClientWidth();

to read the current viewport width. If width < BREAKPOINT, we inject our mobile CSS bundle (for example, mobileStyles.ensureInjected()), which swaps in touch‑friendly layouts and hides desktop‑only elements. Otherwise, we keep the default desktop styles.

To handle user‑driven resizes—when someone drags the browser window or rotates their device—we register a resize handler:

Window.addResizeHandler(event -> {
  int newWidth = event.getWidth();
  if (newWidth < BREAKPOINT) {
    mobileStyles.ensureInjected();
  } else {
    desktopStyles.ensureInjected();
  }
});

This listener means we don’t just detect the breakpoint once; we continuously watch for the window crossing that threshold, dynamically swapping style bundles as needed.

Why this matters:

  • getClientWidth() gives a one‑time measurement on load, ensuring your UI starts in the right mode.
  • addResizeHandler() lets you react to changes—critical for desktop users who resize or tablets that rotate.
  • CSS bundles in GWT let you package and inject only the rules you need (mobile vs. desktop), keeping your CSS lean and avoiding messy overrides in a single stylesheet.

Together, these APIs provide a type‑safe, maintainable way to implement true adaptive behaviour—rather than bolting on media queries to an existing stylesheet, you cleanly separate and inject the appropriate styles at runtime.

Week 3: Begin TopToolbar and TopPanel Development Following Successful Mobile Interface Binding

This week, I began developing the TopPanel—specifically the TopToolbar—after successfully binding our mobile interface. Inheriting all of the desktop styles initially prevented any toolbar changes from appearing on mobile; instead, the app continued to render the parent‑class TopPanel.

During troubleshooting, my mentor, Susan, guided me to a second culprit in the build menu configuration: if the buildDropDown items aren’t explicitly defined, the template silently falls back to the Classic layout. To work around this, she suggested mirroring those menu entries in the mobile menu (and simply hiding the original build menu) so the template can load correctly.

Digging deeper, we found the underlying XML parsers enforce a strict mapping between custom tags and Java classes. These parsers handle our drop‑down buttons without extra Java or CSS, but they’re not very feature‑rich—labels aren’t even supported yet. Although we could refine them later, ensuring every inherited component tag appears in UiBinder was enough to restore the mobile styling for now.

Although the popup‑based approach I initially built might still work, Susan and I opted for a single menu built on our existing framework to guarantee stability. Solving these nested inheritance and parser quirks taught me a valuable lesson about GWT’s markup requirements and reinforced the importance of aligning UiBinder XML with component hierarchies. Despite the week’s frustrations, Week 3 turned into a highly educational deep dive into GWT’s theming and templating mechanics.

Week 4: Implementing Hamburger Menu & PopupPanel via DisclosurePanel

This week’s focus was on replacing our dropdown build menu with a responsive hamburger menu. When tapped, it now opens a PopupPanel containing the full menu and submenus, structured with GWT’s DisclosurePanel.

A DisclosurePanel provides a collapsible header and content area that expands when clicked—perfect for nested submenus. Within our mobile UI, each header acts as a section title (e.g., Build, Settings), and the content panel holds related submenu items.

Why I chose DisclosurePanel + PopupPanel:

  • PopupPanel overlays the rest of the UI and supports auto-hide behaviour and backdrop glass.
  • DisclosurePanel nested inside the popup lets users expand and collapse sub-categories smoothly.

Implementation summary:

  • Tapping the hamburger icon opens a vertical menu panel within a PopupPanel, positioned just next to the icon.
  • Inside the PopupPanel’s UiBinder template, each menu section is wrapped in a <g:DisclosurePanel>, allowing GWT to link these sections to corresponding Java event handlers.
  • Here’s an example of the UiBinder markup:
<ai:DropDownButton name="Settings"
                   styleName="ode-TopPanelButton"
                   ui:field="settingsDropDown"
                   align="left"
                   icon="menu"
                   caption="{messages.menuButton}">
</ai:DropDownButton>

<g:VerticalPanel ui:field="menuContent" visible="false" spacing="10">
  <!-- Projects Section -->
  <g:DisclosurePanel>
    <g:header styleName="mobile-SectionHeader">Projects</g:header>
    <g:VerticalPanel styleName="mobile-SectionPanel">
      <g:Button ui:field="myProjectsButton"
                text="{messages.projectMenuItem}"
                visible="false"/>
      <g:Button ui:field="newButton"
                text="{messages.newProjectMenuItem}"
                visible="{hasWriteAccess}"/>
      <g:Button ui:field="importProjectButton"
                text="{messages.importProjectMenuItem}"
                visible="false"/>

 <!-- Other subMenu Items here -->

    </g:VerticalPanel>
  </g:DisclosurePanel>

  <!-- Additional sections here -->
</g:VerticalPanel>
Enter fullscreen mode Exit fullscreen mode
settingsDropDown.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        LOG.warning("Hamburger menu clicked");
        menuPopup.setWidget(menuContent);
        menuPopup.center();
        menuContent.setVisible(true);
      }
    });
Enter fullscreen mode Exit fullscreen mode

What changed and why it works:

  • Clarified that the vertical menu is shown inside a PopupPanel when the hamburger is tapped.
  • Specified that each section uses DisclosurePanel to enable collapsible behavior and backend event handling.
  • Improved markup readability by aligning attributes and showing how GWT binds UI to Java logic.

Resources I relied on this week:

Week 4 delivered not just a functional hamburger menu, but also strengthened my understanding of GWT’s composable widgets. It’s been a gratifying step toward a more intuitive mobile experience.

Here is my Pr Link:

https://github.com/mit-cml/appinventor-sources/pull/3491

Thank you for reading to the end! I hope you found this post insightful and full of useful takeaways. I’ll be back soon with Week 5’s update—so stay tuned. Until then, keep coding and keep exploring!

A developer toolkit for building lightning-fast dashboards into SaaS apps

A developer toolkit for building lightning-fast dashboards into SaaS apps

Embed in minutes, load in milliseconds, extend infinitely. Import any chart, connect to any database, embed anywhere. Scale elegantly, monitor effortlessly, CI/CD & version control.

Get early access

Top comments (2)

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

this is extremely impressive, reading through your progress makes me want to go back and rebuild half my old interfaces from scratch. where do you think is the real bottleneck for keeping mobile and desktop UIs cleanly separated in these big legacy codebases

Collapse
 
d1vyanshukumar profile image
divyanshu_Kumar

Thanks so much for the kind words! In large legacy UI codebases, the real bottleneck often lies in tightly coupled dependencies, shared services, data models, or UI components that spill over between mobile and desktop layers. Without a clearly defined core layer, teams tend to duplicate logic, which gradually leads to divergence and inconsistency. The lack of documentation or meaningful tests only makes every change feel risky. What has worked well for me is extracting a focused core module that contains business logic and shared contracts, then building two lightweight and isolated shells for mobile and desktop on top of it, without cross-imports. Adding just enough diagrams, documentation, and a few smoke tests around critical flows has also helped keep things maintainable as the code evolves.

Developer-first embedded dashboards

Developer-first embedded dashboards

Embed in minutes, load in milliseconds, extend infinitely. Import any chart, connect to any database, embed anywhere. Scale elegantly, monitor effortlessly, CI/CD & version control.

Get early access

👋 Kindness is contagious

Explore this practical breakdown on DEV’s open platform, where developers from every background come together to push boundaries. No matter your experience, your viewpoint enriches the conversation.

Dropping a simple “thank you” or question in the comments goes a long way in supporting authors—your feedback helps ideas evolve.

At DEV, shared discovery drives progress and builds lasting bonds. If this post resonated, a quick nod of appreciation can make all the difference.

Okay