Skip to main content

Desktop Client Shell

Module: suredms-desktop-client
Source root: SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/

This module is the primary entry point and UI shell for the Java desktop application. It owns the application lifecycle, Swing frame, login flow, ribbon navigation, all named views, the gadget docking framework, the wizard framework, 30+ ribbon actions, and all desktop dialogs.

Purpose

The shell acts as the host process. It initializes the JVM environment, creates the DesktopClient application singleton, mounts views into the docked frame, and coordinates module transitions via NavigationHelper. All feature-specific behavior — quality review, signing, document navigation — is delegated to gadgets and views within this shell or to the quality/signing modules.

Package Structure

PackageContents
com.sureclinical.suredmsBaseLauncher, BaseEntryPoint — startup entry points
com.sureclinical.suredms.uiDesktopClient, NavigationHelper, LoginType, SharedResources, UiExceptionHelper
com.sureclinical.suredms.ui.viewsNamed views: HomeView, ViewView, AcquireView, ShareView
com.sureclinical.suredms.ui.ribbonRibbonMenu, RibbonPanel, TaskBar, ribbon button types
com.sureclinical.suredms.ui.gadgetsBaseGadget, GadgetPane, GadgetDocNav, GadgetMetadata, GadgetDocQueue, stream gadgets, charts
com.sureclinical.suredms.ui.wizardWizardBuilder, WizardDialog, WizardStep, upload/sign/compliance/imaging wizard implementations
com.sureclinical.suredms.ui.actions30+ BaseAction subclasses wired to ribbon menu items
com.sureclinical.suredms.ui.dialogs40+ dialogs for documents, users, organizations, study, system settings
com.sureclinical.suredms.permissionsDocumentPermissionsHelper, FolderPermissionsHelper
com.sureclinical.suredms.securityDigitalIdVerificationDialog, license dialogs, VerificationServiceImpl
com.sureclinical.suredms.services.jobJobManager, UiThreadPool, JobFactory
com.sureclinical.suredms.ui.searchSearchEngineWrapper, quick-find support

Startup Sequence

BaseLauncher

SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/BaseLauncher.java

Two static initializers run before the constructor:

  1. PreferencesUtils.initFolders() — creates working directories; must run first to enable log4j.
  2. DeploymentUtils.applyAllWorkarounds() — applies platform rendering workarounds; on macOS, sets the dock icon via com.apple.eawt.Application reflection.

The constructor then:

  • Installs a global UncaughtExceptionHandler (suppresses ThreadDeath in pool workers).
  • Logs JVM version, heap size, and runtime arguments via RuntimeMXBean.
  • Reads command-line arguments into a parameter map.
  • Uses JFreeChart's ChartFactory with an empty XYSeriesCollection to pre-warm chart rendering.
  • Creates a BaseEntryPoint and hands control to the Application framework.

BaseEntryPoint

SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/BaseEntryPoint.java

Extends JApplet — the desktop client still uses the applet lifecycle model for parameter passing. It is a singleton:

  • getInstance() returns the current entry-point instance; in test mode returns an anonymous stub.
  • getParameter(String key) first checks the command-line parameter map, then falls back to hardcoded defaults: serviceHost = http://127.0.0.1:8080, servicePath = /nuxeo/site/automation-ext.
  • getCodeBase() returns a file:/ URL pointing to the current working directory.
  • destroy() calls DesktopClient.getInstance().exit() and clears the singleton.

DesktopClient

SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/DesktopClient.java

Extends org.jdesktop.application.Application. The central singleton.

Key constants and fields:

FieldValue / TypePurpose
MAX_NUMBER_OF_ACTIVE_ARCHIVES5Hard cap on concurrently open archives
isOnlinebooleanLive connection state
isLockedvolatile booleanLock-screen state
userUserAuthenticated desktop user
ribbonMenuRibbonMenuTop navigation ribbon
enabledModulesSet<String>Feature-flag module keys
loginAsSharedLoginRecordSupport for shared login
bookmarkFileFileBookmark opened on startup (-open)

Lifecycle events use an EventListenerList of DesktopClientEventListener. On login the client:

  • Starts an AutoLogoutThread and a UserNotificationMonitorThread.
  • Installs a KeyEventDispatcher that intercepts Ctrl+G to open GettingStartedDialog.

On logout the client tears down both background threads via interrupt() and calls afterLogout().

Feature gating is implemented via isFeatureEnabled(String featureKey), checked by RibbonMenu.hasPermission(featureKey).

Views

All views extend BaseView, which extends GadgetPanel and implements DesktopClientEventListener. Each view:

  • Has a static ID constant used by AbstractDesktopClientContentPanel.setSelectedView(id).
  • Registers for login/logout events and calls destroy() on logout (nulling all gadget references).
  • Persists gadget layout per user via PreferencesUtils under user.custom.ui.<loginName>.<viewName>.<gadgetName>.
  • Uses CGrid from Bibliothek DockingFrames to position gadgets.

HomeView

SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/views/HomeView.java

The application dashboard after login. Hosts:

GadgetTypePurpose
gadgetAnnouncementsGadgetArticleViewerSystem announcements
gadgetEventsGadgetArticleViewerUpcoming events
gadgetArticlesGadgetArticleViewerNews/articles
gadgetDocumentsOverTimeGadgetChartDocumentsOverTimeDocument volume trend chart
gadgetDocumentsByStudyGadgetChartDocumentsByStudyPer-study document count chart
gadgetStreamGeneratedReportsGadgetStreamGeneratedReportsRecent generated reports
gadgetStreamModifiedDocumentsGadgetStreamModifiedDocumentsRecently modified documents
gadgetStreamModifiedWorkflowsGadgetStreamModifiedWorkflowsActive workflow changes
gadgetStreamOverdueWorkflowsGadgetStreamOverdueWorkflowsOverdue workflow items
gadgetRequiredDocumentsGadgetRequiredDocumentsRequired document compliance
gadgetExpiredDocumentsGadgetExpiredDocumentsExpiring/expired documents
gadgetDocumentsByMilestoneGadgetDocumentsByMilestoneMilestone-based document view
gadgetStreamUserAuditTrailGadgetStreamUserAuditTrailRecent user audit trail
gadgetWorkflowStatusChartsGadgetWorkflowStatusChartsWorkflow status summary charts

ViewView

SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/views/ViewView.java

The primary document browsing view. Hosts:

GadgetPurpose
GadgetDocNavDocument navigator tree/table with multiple view modes
GadgetMetadata (viewer mode)Read-only metadata panel
GadgetMetadata (editor mode)Editable metadata panel
GadgetDocumentWorkflowsWorkflow status and actions for the selected document
GadgetStackStacked viewer area
GadgetIcePDFViewerIn-process PDF renderer
GadgetThumbnailsViewPage thumbnail strip
GadgetDocDiscrepancyViewInline discrepancy display for the selected document

NavigationHelper (SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/NavigationHelper.java) is a static utility class that provides all programmatic navigation within the desktop shell. All calls are dispatched via SwingUtilities.invokeLater (except displayInAcquireView, which is synchronous).

MethodDescription
switchToViewView()Sets the selected view to ViewView.ID
switchToViewViewByCategory()Switches to ViewView and activates DocNavViewMode.BY_CATEGORY
switchToViewViewByReports()Switches to ViewView and activates DocNavViewMode.BY_REPORTS
displayInViewView(DocSearchFilter)Navigates to ViewView and applies the given search filter
displayInViewView(Bookmark)Navigates to ViewView and calls displayBookmark
displayInViewView(BaseEntity)Navigates to ViewView (BY_CATEGORY) and calls displayEntity
displayInViewView(Document)Navigates to ViewView; uses BY_REPORTS for report documents, BY_CATEGORY otherwise
displayInViewView(ContentType)Navigates to ViewView (BY_CATEGORY) and displays the content type
switchToWorkflowView()Switches to "WorkflowPlatformView" or "WorkflowView" based on the WorkflowGlobalParameters.WORKFLOW_PLATFORM_ENABLED feature flag
displayInWorkflowView(Object)Switches to the workflow view and calls baseView.activateObject(object)
displayInAcquireView(Document)Switches to "AcquireView" and calls AcquireView.getInstance().displayDocument(document); returns boolean success

A static VIEW_REPORT_CALLBACK field holds a ReportCallback that calls displayInViewView(report) — used by report generation to auto-navigate on completion.

AcquireView

SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/views/AcquireView.java

The acquire queue view. A singleton (AcquireView.getInstance()). Hosts:

GadgetPurpose
GadgetDocQueueDocument acquire queue with popup menu handler
GadgetDocNavDocument navigator with popup menu handler
GadgetIcePDFViewerPDF viewer for selected queue item
GadgetMetadataMetadata panel for selected document

ShareView

SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/views/ShareView.java

The share/collaboration view. Hosts GadgetShareNavigation and GadgetSharePreview.

Ribbon and Actions

RibbonMenu is an abstract class that extends AbstractAction. Concrete subclasses define the dropdown menus for each ribbon button group.

Key design points:

  • hasPermission(featureKey) delegates to DesktopClient.getInstance().isFeatureEnabled(featureKey).
  • onArchiveOpened(Archive) and onArchiveClosed(Archive) let each menu react to archive lifecycle changes.
  • Menu items are created lazily: initMenu() runs once on first click; refreshMenu() runs on every open to update enabled state.

Action classes in com.sureclinical.suredms.ui.actions (all extend BaseAction):

ActionDescription
ActionOpenArchiveFromNetworkOpens a remote Nuxeo archive
ActionOpenArchiveFromFileOpens a local XML archive file
ActionSaveArchiveToFile / ActionSaveSureDriveToFileExports archive to file
ActionDeleteArchive / ActionDeleteSureDriveDeletes the active archive
ActionLockArchive / ActionLockSureDriveLocks archive
ActionExportStudyContentModel / ActionExportSureDriveContentModelExports CME
ActionArchiveSetup / ActionSureDriveSetupOpens properties/setup dialogs
ActionQualityAssuranceOpens quality assurance setup dialog
ActionPublishPublishes documents
ActionPdfToolOpens PDF tools
ActionMedicalImageUpload / ActionMedicalImageEditorImaging workflows
ActionUserAccount / ActionUserProfile / ActionUserSettingsUser management
ActionSendAlertToUsers / ActionSendMessageToUsersMessaging
ActionShowArticles / ActionShowDraftsArticle/draft browsing
ActionHelp / ActionAbout / ActionExitApplication actions

Wizard Framework

Base class: SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/wizard/WizardBuilder.java

WizardBuilder provides:

  • Configurable dialog title, header, and description via initDialogHeader(resourceKey).
  • Step sequencing via createWizardSteps()List<WizardStep>.
  • Forward/back navigation with per-step validation.
  • Escape-key cancellation, confirmation dialog via cancelQuestion.
  • earlyFinishSupported flag for wizards that allow skipping remaining steps.
  • DialogResultListener callback set called after performWizardAction().
  • Dependency injection via Injector.inject(this).
  • Leak detection via LeakDetector.getInstance().watch(this).

Wizard implementations:

WizardStepsTrigger
UploadWizardBuilderSelect files → Confirm uploadRibbon upload action
SignLocalFileWizardBuilderSelect file → Sign → Download signed fileSign local file action
AuditWizardBuilderSelect study → Select content → Sample size → Create listQuality ribbon
RequiredDocumentWizardBuilderSelect milestone → Required documentCompliance workflow

Permissions

DocumentPermissionsHelper and FolderPermissionsHelper (in com.sureclinical.suredms.permissions) implement permission checks at the document and folder level. Both are consulted by ribbon actions and popup menus to determine which operations to enable.

Background Services

JobManager (SC/suredms-desktop-client-connector/src/main/java/com/sureclinical/suredms/services/job/JobManager.java) is a singleton thread-pool based job queue in the connector module. It schedules and tracks AbstractJob and AbstractProgressJob instances:

  • All long-running operations (uploads, exports, syncs) run as jobs.
  • UiThreadPool dispatches results back to the Swing EDT.
  • JobFactory (suredms-desktop-client/services/job/JobFactory.java) creates typed job instances — it is separate from JobManager and lives in the shell module.
  • JobManagerListener (connector) and JobManagerEvent subscribe to and describe job completion events.

JobManager is retrieved via ServiceProvider.getService(JobManager.class) — it does not have a traditional static singleton getInstance() pattern.

The AutoLogoutThread watches for inactivity and calls the logout flow. UserNotificationMonitorThread polls the server for pending notifications and fires UI events when new items arrive.

Service Registry — ServiceProvider

ServiceProvider (in suredms-common) is a thin wrapper around Java ServiceLoader that discovers and returns IService implementations registered in META-INF/services files:

FeatureManager featureManager = ServiceProvider.getService(FeatureManager.class);
List<SomeSvc> all = ServiceProvider.getServices(SomeSvc.class);

Services are sorted by getServicePriority() descending; the highest-priority instance is returned by getService(). Client-side implementations use ServiceType.ST_CLIENT; server-side use ST_SERVER. For full API details see Data Access Layer.

Feature Flags — FeatureManager

FeatureManager (in suredms-desktop-client-connector) controls which features are available at runtime. FeatureManagerImpl selects between NuxeoFeatureManager (online mode) and SaveFeatureManager (offline mode) at construction time:

boolean hasPdf = featureManager.isFeatureEnabled("FEATURE_PDF_VIEWER");
boolean canView = featureManager.isFeatureEnabled("FEATURE_IMAGE_VIEW", currentUser);

Feature state is snapshotted via FeatureSnapshot. Admins can create named snapshots, list them, inspect details, and roll back to a prior snapshot via restoreSnapshot(id). For the full interface see Data Access Layer.

IcePDF Viewer Gadget

Source: SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/gadgets/icepdf/

The GadgetIcePDFViewer gadget hosts an in-process IcePDF panel for rendering PDF documents without launching an external viewer.

Library: org.icepdf.os:icepdf-pro version 6.2.5-java6 (with icepdf-pro-intl for international font support). jbig2-imageio is included as a JBIG2 decoder plugin.

Rendering runs on a dedicated IcePDF worker thread and results are painted via Java2D. The default icepdf.pro.version property is stub; builds for specific clients override this to enable the full Pro font engine.

Key Classes

ClassRole
GadgetIcePDFViewerTop-level gadget; hosts the IcePDF panel inside a GadgetPanel container
CustomSwingControllerExtends SwingController; adds page-navigation buttons, IcePDFViewerListener list, and JBIG2 page tracking
SureDocumentViewControllerExtends DocumentViewControllerImpl; overrides setDocument() to swap in SureDocumentViewModel without restarting the viewer
SureDocumentViewModelCustom IcePDF document view model
SurePageViewComponentCustom page component with SureDMS-specific rendering hooks
IcePDFToolBarCustom toolbar with navigation, zoom, rotate, and selection controls
IcePDFSearchDialogIn-viewer full-text search dialog
SaveControllerHandles save-with-annotations flow
DocumentBlobPromiseAsync document blob fetcher that resolves to a FileBlob before loading
DownloadPromiseJobBackground AbstractJob that executes a DocumentBlobPromise
CustomAnnotationCallbackReceives IcePDF annotation events for SureDMS-specific handling
SignatureEvent / SignatureListenerSignature field detection events
SelectedPagesDocumentViewView mode that shows only a specified subset of pages

GadgetIcePdfViewerIntegrationTest in suredms-web-start validates PDF rendering in the test environment.

Application Configuration

Source: SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/configuration/

ApplicationConfigurationHelper (com.sureclinical.suredms.configuration) implements server-side application configuration snapshot — export and import of FeatureSnapshot and ArchiveAclRule sets.

Operations

MethodDescription
getVisibility()Returns the current List<ArchiveAclRule> from ArchiveVisibilityHelper.getInstance().getRules()
getExportConfigurationToFileJob()Returns an async AbstractProgressJob that invokes SureOperations.OP_APPLICATION_CONFIGURATION_EXPORT on the server and returns a ByteArrayBlob (Excel) for download
importConfigurationFromFile()Opens a file chooser (.xls filter), parses the selected file via ApplicationConfigurationParser, then shows ApplicationConfigurationImportDialog
importViewVisibility(Map<String, Boolean>)Disables auto-save, applies each view-visibility flag to ArchiveVisibilityHelper and DocNavViewMode, then re-enables auto-save

Import Dialog

ApplicationConfigurationImportDialog (same package) shows a summary of the imported configuration — feature snapshot state and ACL rule counts — and lets the admin confirm before applying.

Move Document Wizard (GAP-12)

Source: SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/wizard/move/MoveDocumentWizardBuilder.java

MoveDocumentWizardBuilder extends WizardBuilder and provides a two-step wizard for renaming and moving documents. Entry points:

MoveDocumentWizardBuilder.showWizard(List<Document> documents);
MoveDocumentWizardBuilder.showWizard(List<Document> documents, DocNavTreeNode treeNode);

Dialog dimensions: 1200 × 800, resizable.

Steps

StepPurpose
DocumentNameStep (wizard.move.step1)Edit document name metadata and form fields
ConfirmationStep (wizard.move.step2)Review selected names and confirm

Context

MoveDocumentWizardContext carries:

  • List<Document> documents — source documents to move
  • nameDocument counterparts — renamed versions
  • Map<Document, List<FormField>> docFieldsMap — metadata fields per document
  • (optional) DocNavTreeNode treeNode — pre-set target folder

Action

On confirm, the wizard builds parallel lists of originals, name-docs, and fields and calls:

DocNavTreeModel2.getInstance().renameDocuments(originals, nameDocs, fields, /*move=*/true);

For batches ≥ 25 documents, a ConfirmationDialog is shown before proceeding.


Look and Feel / Theme System (GAP-15)

Source: SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/ui/laf/LookAndFeelManager.java

LookAndFeelManager (package com.sureclinical.suredms.ui.laf) manages Swing look-and-feel and zoom state for the desktop application. It uses the Substance look-and-feel library (Office 2007 Silver skin) via PushingPixels.

Font Management

MethodDescription
setDefaultFont(String fontName)Sets and persists the default font
setDefaultFont(String fontName, boolean savePreferences)As above; conditionally saves
getDefaultFont()Returns the current default Font
getDefaultFontSmall()Returns the default font at 11pt
getDefaultFontBold()Returns the bold variant of the default font
getFontNames()Returns all system font names

Platform fonts: DEFAULT_FONT_LINUX, DEFAULT_FONT_WINDOWS, DEFAULT_FONT_MAC.

Zoom

MethodDescription
changeZoom(int zoomDelta)Adjusts all font sizes by zoomDelta points
resetZoom()Reverts to the platform default font size

LAF Reload and Listeners

MethodDescription
reloadLookAndFeel()Re-applies the current Substance skin and updates all open windows
setRibbonMode(RibbonMode)Switches ribbon display mode
addLookAndFeelChangeListener(LookAndFeelChangeListener)Subscribes to theme-change events
addZoomChangeListener(ZoomChangeListener)Subscribes to zoom-change events

Share Tab (GAP-18)

The ShareView (already noted in the Views section above) contains two gadgets:

GadgetClassRole
Share navigatorGadgetShareNavigationNavigation tree for shared document context
Share previewGadgetSharePreviewPreview panel for the selected shared item

The Share tab is visible only when FEATURE_SHARE_VIEW or FEATURE_SHARE_VIEW_WITH_DELETION is enabled (checked in StudyDashboardController.canModifyTeam). In the web client, the same feature flag governs the Share tab visibility.

Additional detail panels used within the share context:

  • PersonDetailsPanel — person-specific share detail
  • OrganizationDetailsPanel — organisation-specific share detail
  • StudySubjectDetailsPanel — study subject share detail

Desktop Content Model Editor (GAP-20)

Source: SC/suredms-desktop-client/src/main/java/com/sureclinical/suredms/tempdata/ContentModelEditor.java

ContentModelEditor (package com.sureclinical.suredms.tempdata) is a singleton helper that provides CRUD operations on content model entities (categories, content types, metadata terms) from the desktop shell. Equivalent to the web client's Content Model Editor feature.

ContentModelEditor editor = ContentModelEditor.getInstance();

API

MethodDescription
addCategory(Category)Saves category and parent; reloads; fires entity-data update event
updateCategory(Category)Updates existing category
addContentType(ContentType)Adds a new content type to the repository
updateContentType(ContentType)Updates an existing content type
reserveCategory(Category)Marks a category as reserved (prevents user deletion)
unReserveCategory(Category)Clears the reserved flag
reserveContentType(ContentType)Marks a content type as reserved
unReserveContentType(ContentType)Clears the reserved flag
addOrUpdateMetadataTerm(DataPropertyDef)Persists a metadata term definition via NuxeoClientPool remote operation
updateEntities(Collection<? extends BaseEntity>)Batch-updates multiple entities
canReserve(ContentType)Returns !contentType.isReserved()
canReserve(Category)Recursively checks children for reservable state
canDelete(ContentType)Returns false if documents use this type
canDelete(Category)Returns false if documents use this category
containDocuments(ContentType / Category / Person)Checks for document use
getAnnotations(Archive)Returns List<AnnotationDef> for an archive
getDataProperties(Archive)Returns List<DataPropertyDef> for an archive

Associated UI: LinkMetadataTermDialog (links metadata terms to content types), AssociationAction (ribbon action to open the linking dialog).

Dependencies

ModuleRole
suredms-desktop-client-connectorEndpoint selection and all remote/local data operations
suredms-desktop-client-dataEntity model for session, archives, documents, users
suredms-desktop-client-qualityQualityView mounted by the shell
suredms-desktop-client-signingESignServiceProxy accessed from wizard and ribbon actions

Constraints and Notes

  • MAX_NUMBER_OF_ACTIVE_ARCHIVES = 5 is enforced by DesktopClient; opening a sixth archive fails.
  • All Swing UI construction and updates must run on the EDT. Background work uses JobManager / UiThreadPool.
  • isLocked is volatile; modified by LockScreenDialog from any thread.
  • BaseEntryPoint defaults to http://127.0.0.1:8080 if the parameter map does not contain serviceHost.
  • The KeyEventDispatcher for Ctrl+G is registered once and remains for the application lifetime.
  • Gadget layout positions are stored normalized (0–100 range) relative to the view size and restored on next login.