{"id":13908236,"url":"https://github.com/reportmill/SnapKit","last_synced_at":"2025-07-18T07:30:42.918Z","repository":{"id":39713936,"uuid":"66376193","full_name":"reportmill/SnapKit","owner":"reportmill","description":"A Java UI toolkit","archived":false,"fork":false,"pushed_at":"2025-07-17T15:50:43.000Z","size":7260,"stargazers_count":286,"open_issues_count":0,"forks_count":11,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-07-17T17:47:07.885Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reportmill.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-08-23T14:49:53.000Z","updated_at":"2025-07-17T15:50:47.000Z","dependencies_parsed_at":"2023-02-18T12:03:18.775Z","dependency_job_id":"c6d3ac07-b35f-414c-974a-d2982431db0b","html_url":"https://github.com/reportmill/SnapKit","commit_stats":{"total_commits":1676,"total_committers":2,"mean_commits":838.0,"dds":0.0005966587112171684,"last_synced_commit":"03e8fb7a10ba3c1e6242821c3bb193bb68ddf6fa"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/reportmill/SnapKit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reportmill%2FSnapKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reportmill%2FSnapKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reportmill%2FSnapKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reportmill%2FSnapKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reportmill","download_url":"https://codeload.github.com/reportmill/SnapKit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reportmill%2FSnapKit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265720383,"owners_count":23817224,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-06T23:02:34.164Z","updated_at":"2025-07-18T07:30:42.906Z","avatar_url":"https://github.com/reportmill.png","language":"Java","readme":"# SnapKit - a Java UI toolkit\n\nSnapKit is a modern Java UI library + tools for creating rich Java Client applications that achieve the original\npromise of Java by running pixel-perfect and native on the desktop and in the browser ([WORA](https://en.wikipedia.org/wiki/Write_once,_run_anywhere)).\n\nWhy do we need another UI kit? Because Swing is out of date, JavaFX missed the boat, and neither run natively\nin the browser. But Java desktop development is hard to beat: the iterative dev cycle is fast,\ndebugging is powerful, refactoring is easy, and advanced dev tools solve many problems at compile time.\nThe drawback is deployment: browser deployment is impossible to beat. This situation alone has led to the decline of\nJava Client adoption and prevented it from being a serious contender for most new development.\nSnapKit is designed to resolve this with no compromises.\n\n* [Overview](#Overview)\n* [SnapKit Inspirations](#snapKit-inspirations)\n* [SnapKit Advantages](#snapKit-advantages)\n* [The ViewOwner](#the-viewowner)\n* [The Graphics Package](#the-graphics-package)\n* [The View Package](#the-view-package)\n* [The Text Package](#the-text-package)\n* [The Parser Package](#the-parser-package)\n* [The Properties Package](#the-properties-package)\n* [The 3D Graphics Package](#the-3d-graphics-package)\n* [The Web Package](#the-web-package)\n* [The SnapBuilder UI Builder](#the-snapbuilder-ui-builder)\n* [Integrated Runtime Developer Tools](#integrated-runtime-developer-tools)\n* [Including SnapKit with Gradle and Maven](#including-snapkit-with-gradle-and-maven)\n\nCheck out demos of [SnapKit running in the browser](http://www.reportmill.com/snaptea/):\n\n[ ![SnapKit](https://reportmill.com/snaptea/Samples.png)](http://www.reportmill.com/snaptea/)\n\n\n## Overview\n\nSnapKit runs optimally everywhere via a high level design where low-level functionality (such as painting, user\ninput, system clipboard, drag-and-drop and windowing) is provided via interfaces to the native platform implementation.\nThis makes SnapKit itself comparatively small and simple, light-weight and performant. SnapKit apps run very well in\nthe browser with zero modification with the [CheerpJ browser JVM](https://leaningtech.com/what-is-cheerpj/). When\ncompiled to the browser with a transpiler (via [TeaVM](http://teavm.org)), many apps are only 1 MB in size.\n\n## SnapKit Inspirations\n\nSnapKit is strongly inspired by both Swing and JavaFX. Swing is still a favorite with Java desktop developers, despite\nits age and lack of recent updates. There are still many things developers love:\n\n- Solid view hierarchy and set of controls/components\n- Relatively easy to create and update UI and respond to user input and UI changes\n- Full set of geometric shape primitives: Line, Rect, Ellipse, Path, Polygon, etc.\n- Easily set component borders, fills, and fonts with simple API\n- The whole convenient painting model - just override paint() to customize\n- It handles property changes in conventional Java property change manner\n- It binds easily with POJOs\n\nWhen JavaFX was introduced it rewrote the rulebook for Java UI with dramatic changes, often for the better:\n\n- Easily mix graphics and app controls\n- Easily add gradients, textures, effects\n- Set arbitrary transforms (rotate, scale, skew) on any node\n- It has built-in binding support to easily wire values across objects\n- It has a full set of nodes for easy layout: Box, BorderView, StackPane, etc.\n- It has support for easily defining UI in a separate text file (FXML)\n\n## SnapKit Advantages\n\nSnapKit is the right blend of modern and conventional. SnapKit tries to be more of a \"Swing 2.0\". More precisely, it\nkeeps the basic simplicity and standard conventions of Swing while adding the visual richness of JavaFX and bringing the\nwhole thing to the browser:\n\n- It provides all the essential features of Swing and JavaFX (above)\n- It runs on top of Swing, JavaFX and HTML DOM\n- It is easily portable to any future UI kit and platform\n- The base class is called View (that puts the V in MVC!)\n- The ViewOwner class provides control functionally\n- The ViewEvent class unifies all input events for more consistent handling\n\n    \n## The ViewOwner\n\nThe one thing that may have hurt Swing and JavaFX the most is that there is no standard class to manage the basics of UI\nmanagement: Create, Init, Reset, Respond (otherwise known as the \"Controller\" in MVC).\n    \nThis resulted in confusing controller code, with UI controls often having code for all four functions\nin the same place. Initially this can be deceptively simple and attractive, but falls apart when dozens of inter-dependent\ncontrols are present and order-dependent updates are necessary.\n\nHere is a simple Swing example that quickly gets out of control when extended to many\nproperties and controls:\n\n```\n// Create UI\n_textField = new JTextField();\n\n// Init UI\n_textField.setText(\"Initial Value\");\n\n// Respond UI\n_textField.addActionListener(event -\u003e {\n    _myModel.updatePropertyForTextField(_textField.getText());\n    SwingUtilities.invokeLater(this::updateUI);\n});\n\n// Update UI\npublic void updateUI()\n{\n    _textField.setText(_myModel.getPropertyForTextField());\n});\n```\n\nHere is the same thing with a ViewOwner:\n\n```java\n/** Create UI. */\npublic View createUI()\n{\n    _textField = new TextField();\n    return _textField;\n}\n\n/** Initialize UI. */\npublic void initUI()\n{\n    _textField.setText(\"Initial Value\");\n}\n\n/** Reset UI. */\npublic void resetUI()\n{\n    // Update TextField from Model\n    _textField.setText(_myModel.getPropertyForTextField());\n}\n\n/** Respond UI. */\npublic void respondUI(ViewEvent anEvent)\n{\n    // Update Model from TextField\n    if (anEvent.equals(_textField))\n        _myModel.updatePropertyForTextField(_textField.getText());\n}\n```\n\nSome things to note:\n\n**CreateUI()** is usually handled automatically by loading a '.snp' UI file created in SnapBuilder.\n    \n**InitUI()** is also usually not needed, because UI is configured in createUI() and updated in ResetUI().\n    \n**ResetUI()** updates are deferred, coalesced and \"protected\" (will not cause respondUI() side effects) and\nis called automatically when the user interacts with any UI (or explicitly via resetLater()).\n    \n**RespondUI()** is called automatically by controls (they are preconfigured to do this by default)\n    \n**ResetUI()** and **RespondUI()** make tracking UI interactions convenient and easy by providing a consistent\nplace to look for all get/set code between controls and the model.\n    \n    \n## \u003ca name=\"UniversalAccessors\"\u003eViewOwner \"Universal Accessors\"\u003c/a\u003e\n\nAs a convenience, ViewOwner will let you get/set values using standard methods and support all controls, which\navoids having to lookup or remember specific get/set methods for controls. It also provides common type conversions\nto avoid tedious conversions to/from String/number/boolean formats.\n\n```\npublic void resetUI()\n{\n    // Update MyTextField, MySlider, ...\n    setViewValue(\"MyTextField\", _myModel.getPropertyForTextField());\n    setViewValue(\"MySlider\", _myModel.getPropertyForSlider());\n    ...\n}\n```\n\nThe same applies to ViewEvent (the sole parameter to respondUI()):\n\n```\npublic void respondUI(ViewEvent anEvent)\n{\n    // Handle MyTextField, MySlider, ...\n    if (anEvent.equals(\"MyTextField\"))\n        _myModel.updatePropertyForTextField(anEvent.getStringValue());\n    if (anEvent.equals(\"MySlider\"))\n        _myModel.updatePropertyForSlider(anEvent.getFloatValue());\n    ...\n}\n```\n\nIn addition to get/setViewValue(), there are methods for get/set other View properties: Enabled, Visible, Text,\nSelectedItem, SelectedIndex.\n\n## The Graphics Package\n\nOne of the great aspects of Swing is the separation and synergy between the core graphics layer (Java2D) and\nthe UI layer. SnapKit provides this same separation with the snap.gfx package that contains:\n\n- Full set of geometric primitives: Rect, Point, Size, Insets, Pos (for alignment)\n- Transform for arbitrary transforms and coordinate conversions: rotate, scale, skew\n- Full set of Shape primitives: Rect, RoundRect, Arc, Ellipse, Line, Path, Polygon\n- Paint define fill styles with common subclasses: Color, GradientPaint, ImagePaint\n- Stroke for defining outline style, and Border for a stroke in a specific Paint\n- Effects for rich rendering: Shadow, Reflect, Emboss, Blur\n- Font and FontFile objects (wrap around platform fonts)\n- Painter capable of rendering shapes, images and text with transform, fill, stroke, effect\n- Image object (wraps around platform image)\n- SoundClip for playing sounds\n\n\n## The View Package\n\nThe essentail part of a good UI kit is the set of classes that model the scene graph and standard UI controls.\n\n- View for managing hierarchy of coordinate systems, drawing and input events\n- Full set of classes for graphics primitives: RectView, ShapeView, ImageView, StringView\n- Label: Convenient View+StringView+View layout to easily label UI\n- ButtonBase: Embeds Label for simple, flexible and customizable buttons\n- Button subclasses: Button, CheckBox, ToggleButton RadioButton, MenuButton, MenuItem\n- TextField for editing simple text values (with flexible background label for prompts, icons, etc.)\n- TextView: Comprehensive rich text editing with style setting, spellcheck, etc.\n- ComboBox, Slider, Spinner, ThumbWheel for modifying values with more advanced UI\n- ListView, TableView, TreeView, BrowserView for displaying large sets of objects\n- ParentView for Views that manage children (and ChildView for views that allow others to add them)\n- Box, VBox, HBox, BorderView, StackView, SpringView to facilitate layout\n- ScrollView, SplitView, TabView, TitleView\n- DocView, PageView: represent a real world document and page\n- ViewOwner: integrated controller class to manage UI creation, initialization, updates, bindings and events\n- RootPane: Manages view event dispatch and hierarchy updates, layout and painting\n- WindowView: Maps to a platform window\n- MenuItem, Menu, MenuBar\n- ProgressBar, Separator\n- ViewArchiver for reading/writing views from simple XML files\n- ViewEvent for encapsulating all input events in unified object\n- DialogBox, FormBuilder: For quickly generating UI for common user input\n\n## The Text Package\n\nThe **[snap.text](https://github.com/reportmill/SnapKit/tree/master/src/snap/text)** package provides all\nthe classes necessary to efficiently display and edit large text files and rich text files. There is even\nfundamental support for text with 'tokens' (like source code text files), to efficiently support working\nwith large source files and providing syntax coloring and symbol highlighting.\n\n- TextRun: Manages a group of characters with a display style\n- TextLine: Manages a paragraph of text (with multiple runs)\n- TextModel: Manages lines of styled text\n- TextStyle: Manages a group of text display attributes\n- TextLineStyle: Manages a group of text paragraph attributes (indent, spacing)\n- TextToken: Manages a group of characters in a line that represent a word or code part\n\n## The Parser Package\n\nThe **[snap.parse](https://github.com/reportmill/SnapKit/tree/master/src/snap/parse)** package\ndynamically generates parsers based on conventional grammar files combined with a rule handler class.\nSeparating the grammar from the handler code makes the parser much easier to read, write and maintain.\n\n- Parser: Processes the rules of a grammar to parse a file\n- ParseRule: Represents an individual parse rule with ops for: And, Or, ZeroOrOne, ZeroOrMore, OneOrMore, Pattern, Lookahead\n- ParseHandler: Processes individual parsed nodes for an individual rule to generate an AST\n- Tokenizer: Reads from input to generate individual parse tokens\n- ParseToken: Represents a parsed token\n- Regex: Represents a regex pattern\n\nSeveral parsers are included in SnapKit to parse JSON, XML and Java expressions. Other parsers based on this\npackage to parse PDF and Java are available in separate SnapKit dependent projects.\n\nSee [SnapCode](https://github.com/reportmill/SnapCode) and [SnapPDF](https://github.com/reportmill/SnapPDF).\n\n## The Properties Package\n\nThe **[snap.props](https://github.com/reportmill/SnapKit/tree/master/src/snap/props)** package provides\nan easy way to serialize Java objects and provides automatic support for read/write (JSON/XML), copy/paste,\nundo/redo and more. Specifically the props support provides the following:\n\n- Read/write an object graph to XML and JSON\n- \"Sparse Serialization\" (only write attributes that have changed from default)\n- Clipboard copy/paste an object or object graph\n- Undo/Redo support\n- Automatic support for clone(), equals(), hashCode() and toString()\n\nThis serialization is done by simply defining each serializable property of an object in this fashion:\n\n- Define **string constant** for property name  \n```public static String Name_Prop = \"Name\";```\n\n- Configure prop in **initProps()** method of class  \n```addPropNamed(Name_Prop, \u003cPropClass\u003e, \u003cDefaultValue\u003e)```\n\n- Provide getter in **getPropValue(aPropName)**  \n```if (aPropValue == Name_Prop) return getName();```\n\n- Provide setter in **setPropValue(aPropName,aValue)**  \n```if (aPropValue == Name_Prop) setName((String) aValue);```\n\nHere is an example class that can automatically read/write sparse JSON/XML, handle clipboard copy/pase and handle undo:\n\n```java\n/**\n * This class supports automatic read/write (JSON/XML), clipboard copy/pase, user\n * undo/redo and automatic clone()/equals()/hashCode()/toString() implementations.\n *\n *  To XML: String xmlString = new PropArchiverXML().writeToXML(new MyClass()).getString();\n *\n *  To JSON: String jsonString = new PropArchiverJS().writeToJSON(new MyClass()).getString();\n *\n *  Clone: MyClass myClone = new PropArchiver().copy(new MyClass());\n */\npublic class MyClass extends PropObject {\n\n    // Serialzable Name property\n    private String  _name;\n\n    // Constants for properties\n    public static final String Name_Prop = \"Name\";\n\n    // Constants for property defaults\n    public static final String DEFAULT_NAME = \"John Doe\";\n\n    /**\n     * Constructor.\n     */\n    public MyClass()\n    {\n        _name = DEFAULT_NAME;\n    }\n\n    /**\n     * Override to configure properties for this class.\n     */\n    protected void initProps(PropSet aPropSet)\n    {\n        super.initProps(aPropSet);\n\n        aPropSet.addPropForName(Name_Prop, String.class, DEFAULT_NAME);\n    }\n\n    /**\n     * Override to return propery values for this class.\n     */\n    public Object getPropValue(String aPropName)\n    {\n        switch (aPropName) {\n            case Name_Prop: return getName();\n            default: return super.getPropValue(aPropName);\n        }\n    }\n    \n    /**\n     * Override to set property values for this class.\n     */\n    public void setPropValue(String aPropName, Object aValue)\n    {\n        switch (aPropName) {\n            case Name_Prop: setName((String) aValue); break;\n            default: super.setPropValue(aPropName, aValue); break;\n        }\n    }\n}\n```\n\n## The 3D Graphics Package\n\nThe **[snap.gfx3d](https://github.com/reportmill/SnapKit/tree/master/src/snap/gfx3d)** package provides a\nelegant 3D api based on OpenGL that uses JOGL on the desktop and WebGL in the browser. This allows\nfor write-once-run-anywhere 3D. There is also a simple built-in renderer that renders 3D using standard 2D\ngraphics (this avoids unnecessary external JOGL dependencies when 3D isn't really needed and can actually look better\nin PDF, SVG or print).\n\nThe 3D package has:\n\n- Basic geometry classes for matrices, vectors and points\n- Fundamental scene elements for Camera, Lights and Scene\n- Fundamental VertexArray class to model and render and mesh of triangles, lines and points\n\n[ ![Sample 3D](http://reportmill.com/SnapCharts/Sample3D.png)](https://reportmill.com/SnapCharts/)\n\n## The Web Package\n\nThe **[snap.web](https://github.com/reportmill/SnapKit/tree/master/src/snap/web)** package provides a\nset of classes to abstract and unify interactions with URLs, files and sites (file systems).\n\n- WebURL: Represents a URL for a file from a site\n- WebFile: Represents a file and can return contents (file) or child files (dir)\n- WebSite: Represents a file system or web site and can create or find files by path\n- FileSite, HTTPSite, ZipSite: Implementations of WebSite to support local, remote and compressed files\n\nThese classes make it easy to ambiguously work with files regardless of whether they are from the local file system\nor from a remote HTTP site or even from a Zip archive file, Github repository or DropBox account. The package provides\nunique shared instances of WebFile and WebSite to make it easy to track changes across different modules of code that\nwork with the same files and sites.\n\n## The SnapBuilder UI Builder\n\nBecause the best line of code is the one you don't have to write, UI is almost always created using the UI builder\nand stored in simple XML files ('.snp' files). Simply create/save a .snp file with the same name as your custom ViewOwner class, and the default ViewOwner.createUI() method will load it.\n\nAs a bonus, you can run SnapBuilder in the browser and even open any UI file from a running application using the\n\"Developer Tools Console\", also available in any running app (see below).\n\n[ ![SnapBuilder](https://reportmill.com/snaptea/SnapBuilder/SnapBuilder.gif)](https://reportmill.com/snaptea/SnapBuilder/)\n\n## Integrated Runtime Developer Tools\n\nIf you double-tap the control key in any SnapKit app, a developer console will appear. There are many features\nhere to make it easier to debug visual layouts and explore new or large code bases:\n\n- Mouse-Over to select and inspect any individual nested ViewOwner controller and UI\n- Mouse-Over to select and inspect any View\n- Open any UI in the UI Builder, or controller in GitHub code, or View JavaDoc\n- Select different UI themes (standard, light, dark, light-blue, etc.)\n- Enable debug flashing of repaint regions to ensure efficient repaints\n- Enable Frames-Per-Second paint speed measurement tool\n\n## Including SnapKit with Gradle and Maven\n\nSnapKit can easily be included with build tools like Gradle by referencing the maven package:\n\n```\nrepositories {\n\n    // Maven package repo at reportmill.com\n    maven { url 'https://reportmill.com/maven' }\n}\n\ndependencies {\n\n    // Latest release: https://github.com/reportmill/SnapKit/releases\n    implementation 'com.reportmill:snapkit:2024.10'\n}\n```","funding_links":[],"categories":["HarmonyOS","Projects","项目"],"sub_categories":["Windows Manager","GUI"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freportmill%2FSnapKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freportmill%2FSnapKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freportmill%2FSnapKit/lists"}