blob: d6f29681def3604e57e11810f1fac45dad1f1678 [file] [log] [blame]
<!doctype html>
<html class="no-js" lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>NetBeans Platform Gesture Collection Infrastructure Tutorial</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="NetBeans Platform Gesture Collection Infrastructure Tutorial - Apache NetBeans">
<meta name="author" content="Apache NetBeans">
<meta name="description" content="NetBeans Platform Gesture Collection Infrastructure Tutorial - Apache NetBeans">
<meta name="keywords" content="Apache NetBeans Platform, Platform Tutorials, NetBeans Platform Gesture Collection Infrastructure Tutorial">
<meta name="generator" content="Apache NetBeans">
<link rel="stylesheet" href="../../../../_/css/font-awesome.min.css">
<link rel="alternate" type="application/atom+xml" title="Apache NetBeans Blog" href="https://netbeans.apache.org/blogs/atom" />
<link rel="stylesheet" href="../../../../_/css/highlightjs/default.min.css">
<link rel="stylesheet" href="../../../../_/css/netbeans.css">
<link rel="apple-touch-icon" sizes="180x180" href="../../../../_/images/fav/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="../../../../_/images/fav/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="../../../../_/images/fav/favicon-16x16.png">
<link rel="manifest" href="../../../../_/images/fav/site.webmanifest">
<link rel="mask-icon" href="../../../../_/images/fav/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#ffc40d">
<meta name="theme-color" content="#ffffff">
<link href="../../../../_/css/font-open-sans.css" rel="stylesheet">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
</head>
<body>
<div class="title-bar" data-responsive-toggle="responsive-menu" data-hide-for="medium">
<button type="button" data-toggle="responsive-menu"><i style='font-size: 32px; color: #fff; padding: 8px' class='fa fa-bars'></i></button>
<div class="title-bar-title">Apache NetBeans</div>
</div>
<div class="top-bar" id="responsive-menu">
<div class='top-bar-left'>
<a class='title' href="../../../../index.html"><img src='../../../../_/images/apache-netbeans.svg' style='padding: 8px; height: 48px;'> Apache NetBeans</a>
</div>
<div class="top-bar-right">
<ul class="vertical medium-horizontal menu" data-responsive-menu="drilldown medium-dropdown">
<li> <input id="search-input" type="text" placeholder="Search the docs"> </li>
<li> <a href="../../../../front/main/community">Community</a> </li>
<li> <a href="../../../../front/main/participate">Participate</a> </li>
<li> <a href="../../../../front/main/blogs">Blog</a></li>
<li> <a href="../../../../front/main/help">Get Help</a> </li>
<li> <a href="https://plugins.netbeans.apache.org/">Plugins</a> </li>
<li> <a href="../../../../front/main/download">Download</a> </li>
</ul>
</div>
</div>
<!-- src/templates/news -->
<section class="hero news alternate">
<div class='grid-container'>
<div class='cell'>
<div class="annotation">Latest release</div>
<h1>Apache NetBeans 27</h1>
<p><a class="button success" href="../../../../front/main/download/nb27">Download</a></p>
</div>
</div>
</section>
<div class='grid-container main-content tutorial'>
<h1 class="sect0">NetBeans Platform Gesture Collection Infrastructure Tutorial</h1>
<div class="sectionbody">
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon"><i class="fa icon-note" title="Note"></i></td>
<td class="content">This tutorial needs a review.
You can <a href="https://github.com/apache/netbeans-antora-tutorials/edit/main/modules/ROOT/pages/tutorials/nbm-gesture.adoc" title="Edit this tutorial in github">edit it in GitHub </a>
following these <a href="../../../../tutorial/main/kb/docs/contributing">contribution guidelines.</a></td>
</tr></tbody>
</table>
</div>
</div>
<div id="toc" class="toc">
<div id="toctitle"></div>
<ul class="sectlevel1">
<li><a href="#_setting_up_the_gesture_collecting_infrastructure">Setting Up the Gesture Collecting Infrastructure</a></li>
<li><a href="#_logging_ui_gestures">Logging UI Gestures</a></li>
<li><a href="#_submitting_ui_gestures">Submitting UI Gestures</a></li>
<li><a href="#_accepting_ui_gestures">Accepting UI Gestures</a></li>
<li><a href="#_visualizing_ui_gestures">Visualizing UI Gestures</a></li>
<li><a href="#_further_reading">Further Reading</a></li>
</ul>
</div>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Do you know what your users are doing with your NetBeans Platform application? Which windows are they opening? Which actions are they commonly invoking? When are they clicking the "Help" button on a dialog? Knowing the answers to these questions is crucial in determining where you should be assigning development resources. Knowing that the "Help" button is being pressed a lot for a particular feature might indicate that there is a problem with the UI that you could consider modifying in some way.</p>
</div>
<div class="paragraph">
<p>Also, the priority of bugs can be determined, at least partially, by how frequently something is actually being used. When someone files a P1 bug and writes e-mails demanding you fix something, wouldn&#8217;t it be helpful to find out that the buggy feature in question is only being used by 2% of your user base?</p>
</div>
<div class="paragraph">
<p>The usefulness of knowing what users are doing with your application is limitless. Time to add a user interface gesture collector to your application. NetBeans IDE has such a collector and, since your application is built on the same infrastructure (i.e., the NetBeans Platform), you can make use of that same gesture collecting infrastructure.</p>
</div>
<div class="paragraph">
<p>In this tutorial, you are introduced to setting up the NetBeans Platform gesture collection infrastructure and to using it in a NetBeans Platform application. You will analyze how heavily the "brush size change" feature in the NetBeans Paint Application is used:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigestureserver-5.png" alt="gesture 70 uigestureserver 5">
</div>
</div>
<div class="paragraph">
<p>By the end of this tutorial, you should have a general understanding of how the gesture collection infrastructure fits together and have a basic idea of how to create your own statistics and where to go for further information.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_setting_up_the_gesture_collecting_infrastructure"><a class="anchor" href="#_setting_up_the_gesture_collecting_infrastructure"></a>Setting Up the Gesture Collecting Infrastructure</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When setting up the gesture collecting infrastructure, you need to enable certain modules that are disabled by default in your NetBeans Platform application.</p>
</div>
<div class="paragraph">
<p>If you want to try out these instructions on an actual application prior to trying them out on your own sources, you can use the NetBeans Platform Paint Application, which you can get from the Samples category in the New Project wizard (Ctrl-Shift-N). That is the example application that will be referred to throughout this tutorial.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="1">
<li>
<p>In the Projects window, right-click your application and choose Properties. In the Project Properties dialog, click "Libraries".</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>1.
Check the "nb" checkbox, then check the following three checkboxes to add the related modules to the application:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>UI Gestures Collector Infrastructure</p>
</li>
<li>
<p>UI Handler Library</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You should now see the following:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_enable-infrastructure.png" alt="gesture 70 enable infrastructure">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_logging_ui_gestures"><a class="anchor" href="#_logging_ui_gestures"></a>Logging UI Gestures</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A UI collecting gesture, that is, an event that will be identified as a UI gesture, is considered to be everything that is logged into the "org.netbeans.ui" logger. In this section you are shown how to use this logger.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="1">
<li>
<p>In the <code>PaintTopComponent</code> , change the <code>stateChanged</code> method so that a new gesture log is created whenever the brush size changes:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Override
public void stateChanged(ChangeEvent e) {
int brushSize = brushSizeSlider.getValue();
canvas.setBrushDiameter(brushSize);
String UI_LOGGER_NAME = "org.netbeans.ui.brushsize";
LogRecord record = new LogRecord(Level.INFO, "BRUSH_SIZE_CHANGED");
record.setParameters(new Object[]{brushSize});
record.setLoggerName(UI_LOGGER_NAME);
Logger.getLogger(UI_LOGGER_NAME).log(record);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Read more about <a href="http://download.oracle.com/javase/6/docs/api/java/util/logging/LogRecord.html"> <code>java.util.logging.LogRecord</code> </a>.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>Run the application. Make the gesture a few times, that is, change the brush size a few times, using the "Brush Size" slider, shown below:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_brush-change.png" alt="gesture 70 brush change">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="3">
<li>
<p>Close the application and notice that the following file exists in the "build/testuserdir/var/log" folder, which is visible if the Files window (Ctrl-2) is open in the IDE:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_gesture-collected.png" alt="gesture 70 gesture collected">
</div>
</div>
<div class="paragraph">
<p>Whenever the brush size changes, a new entry such as the following is added to the "uigestures" file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;record&gt;
&lt;date&gt;2011-05-12T16:42:30&lt;/date&gt;
&lt;millis&gt;1305211350828&lt;/millis&gt;
&lt;sequence&gt;102&lt;/sequence&gt;
&lt;level&gt;INFO&lt;/level&gt;
&lt;thread&gt;12&lt;/thread&gt;
&lt;message&gt;BRUSH_SIZE_CHANGED&lt;/message&gt;
&lt;param&gt;24&lt;/param&gt;
&lt;/record&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>You have now learned how to collect UI gestures. Let&#8217;s now learn how to submit them to the server.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_submitting_ui_gestures"><a class="anchor" href="#_submitting_ui_gestures"></a>Submitting UI Gestures</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this section, you learn how to submit gestures to the server. By default, gestures are automatically submitted once there are 1000 gestures in the "uigestures" folder. In addition to that, in this example we are going to let the user specify when the gestures are to be sent, interactively, via a button in the toolbar.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="1">
<li>
<p>Follow <a href="http://netbeans.dzone.com/news/including-nbm-files-netbeans">these instructions</a> to incorporate this plugin into your application: <a href="https://builds.apache.org/view/M-R/view/NetBeans/job/netbeans-linux/lastSuccessfulBuild/artifact/nbbuild/nbms/platform/org-netbeans-modules-uihandler.nbm">org-netbeans-modules-uihandler-interactive.nbm</a></p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Add this target to your application&#8217;s "build.xml" file and then the NBM you have downloaded above will always be copied into the right folder whenever you build the application, assuming the NBM file is in the same folder as the "build.xml" file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;target name="build" depends="suite.build"&gt;
&lt;copy todir="build/cluster/update/download" &gt;
&lt;fileset file="org-netbeans-modules-uihandler-interactive.nbm"/&gt;
&lt;/copy&gt;
&lt;echo message="copied the interactive ui handler into cluster/update/download" /&gt;
&lt;/target&gt;</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>Run the application and notice that you now have a new button in the toolbar, which can be used for submitting gestures to the server:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigesture-submit.png" alt="gesture 70 uigesture submit">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="3">
<li>
<p>Click the button and you see this dialog:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_welcome-uigesture.png" alt="gesture 70 welcome uigesture">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="4">
<li>
<p>Click "View Data" and you see this dialog, showing the data that is ready to be submitted:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_data-dialog.png" alt="gesture 70 data dialog">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="5">
<li>
<p>Now we will change the location for submitting the gestures. By default, gestures are submitted here:</p>
</li>
</ol>
</div>
<div class="paragraph">
<p><a href="https://netbeans.org/nonav/uigestures/index3.html">http://netbeans.org/nonav/uigestures/index3.html</a></p>
</div>
<div class="paragraph">
<p>Look in the source of that location and you will see this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;&lt;/meta&gt;
&lt;title&gt;Welcome to UI Gestures Collector&lt;/title&gt;
&lt;link rel="stylesheet" type="text/css" href="https://netbeans.org/nonav/uigestures/index.css"&gt;&lt;/link&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;
You can now submit data about the UI actions you did in the IDE and
help us make NetBeans better. &lt;a href="https://netbeans.org/nonav/uigestures/info2.html"&gt;
Read more...&lt;/a&gt;
&lt;/p&gt;
&lt;!--
&lt;form action="https://netbeans.org/uigestures/post2.html" method="post"&gt;
--&gt;
*&lt;form action="http://statistics.netbeans.org/analytics/upload.jsp" method="post"&gt;*
&lt;input type="hidden" name="submit" value="&amp;amp;Submit Data"&gt;&lt;/input&gt;
&lt;input type="hidden" name="auto-submit" value="&amp;amp;Automatic Submit"&gt;&lt;/input&gt;
&lt;input type="hidden" name="view-data" value="&amp;amp;View Data" align="left" alt="&amp;amp;Hide Data"&gt;&lt;/input&gt;
&lt;input type="hidden" name="exit" value="&amp;amp;Cancel"&gt;&lt;/input&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Gestures for NetBeans IDE are visualized at <a href="http://statistics.netbeans.org/analytics/">http://statistics.netbeans.org/analytics/</a>.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="6">
<li>
<p>You need to create an XHTML page similar to the above, but pointing to your own location for receiving gestures. For example:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html hljs" data-lang="html">&lt;h2&gt;UI Gestures Collector&lt;/h2&gt;
&lt;p&gt;Welcome to UI Gestures Collector&lt;/p&gt;
&lt;p&gt;You can now submit data about the UI actions you performed.&lt;/p&gt;
&lt;form action="http://localhost:8888/analytics/upload.jsp" method="post"&gt;
&lt;input name="submit" value="&amp;amp;Submit Data" type="hidden"&gt;
&lt;input name="exit" value="&amp;amp;Cancel" type="hidden"&gt;
&lt;/form&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Later in this tutorial you will learn how to use the "upload.jsp" referred to above.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="7">
<li>
<p>Now that we have a site that will handle our gestures, we need to customize the gesture collecting infrastructure to use that site rather than the default. The site used for this purpose is specified by the WELCOME_URL key in a bundle in the "uihandler" module. You now need to brand the value of the WELCOME_URL key to point to where your site for handling gestures is found. Right-click on the Paint Application and choose "Branding". In the Branding editor, use the Resource Bundles tab to look for "uigestures". You will find several values returned, as shown below, including "WELCOME_URL":</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_brand-ui-gesture.png" alt="gesture 70 brand ui gesture">
</div>
</div>
<div class="paragraph">
<p>Right-click on the WELCOME_URL item above and choose "Add To Branding". Then replace the above with the location of your own UI gesture handling location.</p>
</div>
<div class="paragraph">
<p>By means of the indirection provided by the gesture collection XHTML page shown above, you can easily switch to different servers or change the buttons shown in the page or even shutdown the service completely, simply by editing the XHTML page.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_accepting_ui_gestures"><a class="anchor" href="#_accepting_ui_gestures"></a>Accepting UI Gestures</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this section, you learn how to accept gestures.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="1">
<li>
<p>Install Mercurial and run this command:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">hg clone http://hg.netbeans.org/main/misc</code></pre>
</div>
</div>
<div class="paragraph">
<p>You should see something like the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">C:\Documents and Settings\gwielenga\uigesture&gt;hg clone http://hg.netbeans.org/main/misc
destination directory: misc
requesting all changes
adding changesets
adding manifests
adding file changes
added 5854 changesets with 22833 changes to 7178 files
updating to branch default
4995 files updated, 0 files merged, 0 files removed, 0 files unresolved</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>In the Files window, browse to the location where you did your clone and you should be able to open "misc/logger/uihandlerserver" as a NetBeans project, as shown below:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigestureserver-1.png" alt="gesture 70 uigestureserver 1">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="3">
<li>
<p>On the command line, go to the location above, that is, go to "misc/logger/uihandlerserver" and then run:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">ant</code></pre>
</div>
</div>
<div class="paragraph">
<p>The above command will download many required JARs and compile the application. The application should now look as follows in the IDE:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigestureserver-2.png" alt="gesture 70 uigestureserver 2">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="4">
<li>
<p>Run the application and go to this site:</p>
</li>
</ol>
</div>
<div class="paragraph">
<p><a href="http://localhost:8888/">http://localhost:8888/</a></p>
</div>
<div class="paragraph">
<p>The analytics application should start and you should see a default analytics page in your browser.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="5">
<li>
<p>Now we&#8217;re going to set up our NetBeans Platform application to use the redirect page that is in the deployed application, at "misc/logger/uihandlerserver/redirect.xhtml". Do this by opening the application&#8217;s <code>project.properties</code> file and then adding this line, changing it where necessary to match your own file location:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">run.args.extra=-J-Dorg.netbeans.modules.uihandler.LoadURI=file:///"C:/Documents and Settings/gwielenga/uigesture/misc/logger/uihandlerserver/redirect.xhtml"</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="6">
<li>
<p>When the application starts up, click the UI Gesture button, then click "Submit Data" a few times, refresh the page in the browser, and you should see something like this, taking note of the top right corner, where the data is incremented:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigestureserver-3.png" alt="gesture 70 uigestureserver 3">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="7">
<li>
<p>Look in the "uihandlerserver/build/logs" folder and you&#8217;ll see a new file added each time data is submitted to the server:</p>
</li>
</ol>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigestureserver-4.png" alt="gesture 70 uigestureserver 4">
</div>
</div>
<div class="paragraph">
<p>You have now learned about the Analytics application and how to use it to accept gestures from the user.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_visualizing_ui_gestures"><a class="anchor" href="#_visualizing_ui_gestures"></a>Visualizing UI Gestures</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this section, you learn how to visualize gestures. You will do so by working with three files in the Analytics application. You will create a Statistic class:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_sample-1.png" alt="gesture 70 sample 1">
</div>
</div>
<div class="paragraph">
<p>You will also create a JSP file:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_sample-2.png" alt="gesture 70 sample 2">
</div>
</div>
<div class="paragraph">
<p>Finally, you will tweak an existing file, which defines the sidebar of the application:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_sample-3.png" alt="gesture 70 sample 3">
</div>
</div>
<div class="paragraph">
<p>To learn about the different ways of visualizing gestures, you are advised to examine the existing statistic classes and JSP files in the application. These are used by the <a href="http://statistics.netbeans.org/analytics/">NetBeans statistics community</a> and can serve as examples for your own statistics.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="1">
<li>
<p>Let&#8217;s first create a statistic:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">package org.netbeans.server.uihandler.statistics;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.LogRecord;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.servlet.jsp.PageContext;
import org.netbeans.server.uihandler.Statistics;
import org.netbeans.server.uihandler.statistics.BrushSizeChangeStatistic.DataBean;
import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = Statistics.class)
public class BrushSizeChangeStatistic extends Statistics {
private static final DataBean EMPTY = new DataBean(0, 0, 0);
public static final String STATISTIC_NAME = "BrushSizeChangeStatistic";
public BrushSizeChangeStatistic() {
super(STATISTIC_NAME);
}
@Override
protected DataBean newData() {
return EMPTY;
}
@Override
protected DataBean process(LogRecord rec) {
if ("BRUSH_SIZE_CHANGED".equals(rec.getMessage())) {
return new DataBean(1, 0, 0);
} else {
return EMPTY;
}
}
@Override
protected DataBean finishSessionUpload(String userId, int sessionNumber, boolean initialParse, DataBean d) {
int nonNullSessions = 0;
if (d.getActionsCount() &gt; 0) {
nonNullSessions = 1;
}
return new DataBean(d.getActionsCount(), 1, nonNullSessions);
}
@Override
protected DataBean join(DataBean one, DataBean two) {
return new DataBean(one.getActionsCount() + two.getActionsCount(),
one.getNumberOfSessions() + two.getNumberOfSessions(),
one.getNumberOfNonNullSessions() + two.getNumberOfNonNullSessions());
}
@Override
protected void write(Preferences pref, DataBean d) throws BackingStoreException {
pref.putInt("all", d.getActionsCount());
pref.putInt("sessions", d.getNumberOfSessions());
pref.putInt("non_null_sessions", d.getNumberOfNonNullSessions());
}
@Override
protected DataBean read(Preferences pref) throws BackingStoreException {
return new DataBean(pref.getInt("all", 0), pref.getInt("sessions", 0), pref.getInt("non_null_sessions", 0));
}
@Override
protected void registerPageContext(PageContext page, String name, DataBean data) {
page.setAttribute(name + "Usages", data.getUsages());
}
public static final class DataBean {
private final int actionsCount;
private final int numberOfSessions;
private final int numberOfNonNullSessions;
public DataBean(int actionsCount, int numberOfSessions, int numberOfNonNullSessions) {
this.actionsCount = actionsCount;
this.numberOfSessions = numberOfSessions;
this.numberOfNonNullSessions = numberOfNonNullSessions;
}
public int getActionsCount() {
return actionsCount;
}
public int getNumberOfSessions() {
return numberOfSessions;
}
public int getNumberOfNonNullSessions() {
return numberOfNonNullSessions;
}
public Map getUsages() {
Map usages = new HashMap();
usages.put("brush changed", numberOfNonNullSessions);
usages.put("brush not changed", numberOfSessions - numberOfNonNullSessions);
return usages;
}
}
}</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>Next, we need to display our statistic in some way:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;%@page contentType="text/html"%&gt;
&lt;%@page pageEncoding="UTF-8"%&gt;
&lt;%@ taglib uri="/WEB-INF/statistics.tld" prefix="ui" %&gt;
&lt;c:set var="path" value='/ &lt;a href="../index.jsp"&gt;Analytics&lt;/a&gt; / Graph / Brush Size'/&gt;
&lt;%@include file="/WEB-INF/jspf/header.jspf" %&gt;
&lt;ui:useStatistic name="BrushSizeChangeStatistic"/&gt;
&lt;h2&gt;Brush Size Change Analysis&lt;/h2&gt;
&lt;ui:pie
collection="globalBrushSizeChangeStatisticUsages"
category="key"
value="value"
title="In how many logs was there a brush size change?"
resolution="600x200"
/&gt;
&lt;%@include file="/WEB-INF/jspf/footer.jspf" %&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>It is important to understand how the JSP page above is linked to the statistic class that we created earlier:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Tag Library.</strong> We use a tag library that provides the "useStatistic" tag, in line 6 above. The "useStatistic" tag injects the statistics data into the JSP page. To create characters we use the statistic tag library, together with, in this case, its pie tag. The "useStatistic" tag injects the data that your statistic has created into the JSP page. In our case we don&#8217;t need to preprocess the data first because the pie chart tag accepts a collection and it doesn&#8217;t need to know nothing about our <code>DataBean</code> .</p>
</li>
<li>
<p><strong>Collection Name.</strong> The name of the collection specified above, in line 11, is "globalBrushSizeChangeStatisticUsages". The prefix, "global", specifies that we want to see the overall statistics, rather than "user" and "last". The "last" prefix contains only data counted for the last submitted log, while the "user" prefix contains all the data from the submitter. The middle part of the name is "BrushSizeChangeStatistic", which is the name of the statistic that has calculated the data, while the suffix "Usages" was added in the statistic&#8217;s "registerPageContext" method so that different charts can be distinguished.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>1.
Run the Analytics application and also run the Paint application. Submit a few logs and then go to this location:</p>
</div>
<div class="paragraph">
<p><a href="http://localhost:8888/analytics/graph/brushsize.jsp">http://localhost:8888/analytics/graph/brushsize.jsp</a></p>
</div>
<div class="paragraph">
<p>Below, you can see that 7 logs have been submitted and that the majority of them indicate that the brush size change feature is not used a lot:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigestureserver-5.png" alt="gesture 70 uigestureserver 5">
</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="4">
<li>
<p>Now, let&#8217;s add a bar chart, together with the pie chart used above:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;%@page contentType="text/html"%&gt;
&lt;%@page pageEncoding="UTF-8"%&gt;
&lt;%@ taglib uri="/WEB-INF/statistics.tld" prefix="ui" %&gt;
&lt;c:set var="path" value='/ &lt;a href="../index.jsp"&gt;Analytics&lt;/a&gt; / Graph / Brush Size'/&gt;
&lt;%@include file="/WEB-INF/jspf/header.jspf" %&gt;
&lt;ui:useStatistic name="BrushSizeChangeStatistic"/&gt;
&lt;h2&gt;Brush Size Change Analysis&lt;/h2&gt;
&lt;ui:pie
collection="globalBrushSizeChangeStatisticUsages"
category="key"
value="value"
title="Number of logs with a brush size change"
resolution="600x200"
/&gt;
&lt;ui:bar
collection="globalBrushSizeChangeStatisticAvg"
category="name"
value="value"
serie="name"
stacked="true"
title="Average count of brush size changes"
resolution="300x400"
/&gt;
&lt;%@include file="/WEB-INF/jspf/footer.jspf" %&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is what we&#8217;d like to see, that is, a bar chart showing averages, together with our pie chart:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_uigestureserver-6.png" alt="gesture 70 uigestureserver 6">
</div>
</div>
<div class="paragraph">
<p>Therefore, we need to add a new calculation to our BrushSizeChangeStatistic.</p>
</div>
<div class="olist arabic">
<ol class="arabic" start="5">
<li>
<p>In the <code>BrushSizeChangeStatistic</code> class, add the following to the <code>DataBean</code> :</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">private Collection&lt;ViewBean&gt; getAvgData() {
List&lt;ViewBean&gt; vb = new ArrayList&lt;ViewBean&gt;();
vb.add(new ViewBean("AVG for all logs", actionsCount / numberOfSessions));
vb.add(new ViewBean("AVG for users of brush change", actionsCount / numberOfNonNullSessions));
return vb;
}
public static final class ViewBean {
private final String name;
private final Integer value;
public ViewBean(String name, Integer value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public Integer getValue() {
return value;
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then expose the above via the line in bold below in the <code>registerPageContext</code> :</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Override
protected void registerPageContext(PageContext page, String name, DataBean data) {
page.setAttribute(name + "Usages", data.getUsages());
*page.setAttribute(name + "Avg", data.getAvgData());*
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now you know how to visualize gestures received from the user. Refer to the files shown earlier and treat them as examples for your own statistics. In the "statistics" package, explore the available statistics:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_sample-1.png" alt="gesture 70 sample 1">
</div>
</div>
<div class="paragraph">
<p>Then learn how to render them, by looking at the JSPs in the "graph" folder:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../_images/tutorials/gesture_70_sample-2.png" alt="gesture 70 sample 2">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_further_reading"><a class="anchor" href="#_further_reading"></a>Further Reading</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This concludes the NetBeans Platform Gesture Collector Tutorial. This document has described how to collect user interface gestures from the users of a NetBeans Platform application. For more information about gesture collecting on the NetBeans Platform, see the following resources:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="http://statistics.netbeans.org/analytics/">NetBeans Analytics Community</a></p>
</li>
<li>
<p><a href="https://bits.netbeans.org/dev/javadoc/org-netbeans-modules-uihandler/overview-summary.html">UI Gestures Collector Infrastructure</a></p>
</li>
<li>
<p><a href="../../../../wiki/main/wiki/UIGesturesCollector/" class="xref page">UIGesturesCollector</a></p>
</li>
<li>
<p><a href="../../../../wiki/main/wiki/HowToUseUIGesturesCollectorInYourApp/" class="xref page">HowToUseUIGesturesCollectorInYourApp</a></p>
</li>
<li>
<p><a href="../../../../front/main/blogs/geertjan/collecting_data_on_users_of/" class="xref page">Collecting Data on Users of a NetBeans Platform Application</a></p>
</li>
<li>
<p><a href="http://weblogs.java.net/blog/fvo/archive/2010/11/22/slowness-detection-netbeans-rcp-applications">Slowness Detection in NetBeans RCP Applications</a></p>
</li>
<li>
<p><a href="https://bits.netbeans.org/dev/javadoc/org-openide-util/org/openide/util/doc-files/logging.html">Logging in NetBeans</a></p>
</li>
</ul>
</div>
</div>
</div>
<section class='tools'>
<ul class="menu align-center">
<li><a title="Facebook" href="https://www.facebook.com/NetBeans"><i class="fa fa-md fa-facebook"></i></a></li>
<li><a title="Twitter" href="https://twitter.com/netbeans"><i class="fa fa-md fa-twitter"></i></a></li>
<li><a title="Github" href="https://github.com/apache/netbeans"><i class="fa fa-md fa-github"></i></a></li>
<li><a title="YouTube" href="https://www.youtube.com/user/netbeansvideos"><i class="fa fa-md fa-youtube"></i></a></li>
<li><a title="Atom Feed" href="https://netbeans.apache.org/blogs/atom"><i class="fa fa-mf fa-rss"></i></a></li>
<li><a title="Slack" href="https://tinyurl.com/netbeans-slack-signup/"><i class="fa fa-md fa-slack"></i></a></li>
<li><a title="Issues" href="https://github.com/apache/netbeans/issues"><i class="fa fa-mf fa-bug"></i></a></li>
</ul>
<ul class="menu align-center">
<li><a href="https://github.com/apache/netbeans-antora-tutorials/edit/main/modules/ROOT/pages/tutorials/nbm-gesture.adoc" title="See this page in github"><i class="fa fa-md fa-edit"></i> See this page in GitHub.</a></li>
</ul>
</section>
</div>
<div class='grid-container incubator-area' style='margin-top: 64px'>
<div class='grid-x grid-padding-x'>
<div class='large-auto cell text-center'>
<a href="https://www.apache.org/">
<img style="height: 60px" title="Apache Software Foundation" src="../../../../_/images/asf_logo_wide.svg" />
</a>
</div>
<div class='large-auto cell text-center'>
<a href="https://www.apache.org/events/current-event.html">
<img style="width:234px; height: 60px;" title="Apache Software Foundation current event" src="https://www.apache.org/events/current-event-234x60.png"/>
</a>
</div>
</div>
</div>
<footer>
<div class="grid-container">
<div class="grid-x grid-padding-x">
<div class="large-auto cell">
<h1><a href="../../../../front/main/about">About</a></h1>
<ul>
<li><a href="../../../../front/main/community/who">Who's Who</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://www.apache.org/security/">Security</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/community">Community</a></h1>
<ul>
<li><a href="../../../../front/main/community/mailing-lists">Mailing lists</a></li>
<li><a href="../../../../front/main/community/committer">Becoming a committer</a></li>
<li><a href="../../../../front/main/community/events">NetBeans Events</a></li>
<li><a href="https://www.apache.org/events/current-event.html">Apache Events</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/participate">Participate</a></h1>
<ul>
<li><a href="../../../../front/main/participate/submit-pr">Submitting Pull Requests</a></li>
<li><a href="../../../../front/main/participate/report-issue">Reporting Issues</a></li>
<li><a href="../../../../front/main/participate/#documentation">Improving the documentation</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/help">Get Help</a></h1>
<ul>
<li><a href="../../../../front/main/help/#documentation">Documentation</a></li>
<li><a href="../../../../wiki/main/wiki">Wiki</a></li>
<li><a href="../../../../front/main/help/#support">Community Support</a></li>
<li><a href="../../../../front/main/help/commercial-support">Commercial Support</a></li>
</ul>
</div>
<div class="large-auto cell">
<h1><a href="../../../../front/main/download">Download</a></h1>
<ul>
<li><a href="../../../../front/main/download">Releases</a></li>
<li><a href="https://plugins.netbeans.apache.org/">Plugins</a></li>
<li><a href="../../../../front/main/download/#_daily_builds_and_building_from_source">Building from source</a></li>
<li><a href="../../../../front/main/download/#_older_releases">Previous releases</a></li>
</ul>
</div>
</div>
</div>
</footer>
<div class='footer-disclaimer'>
<div class="footer-disclaimer-content">
<p>Copyright &copy; 2017-2025 <a href="https://www.apache.org">The Apache Software Foundation</a>.</p>
<p>Licensed under the Apache <a href="https://www.apache.org/licenses/">license</a>, version 2.0</p>
<div style='max-width: 40em; margin: 0 auto'>
<p>Apache, Apache NetBeans, NetBeans, the Apache feather logo and the Apache NetBeans logo are trademarks of <a href="https://www.apache.org">The Apache Software Foundation</a>.</p>
<p>Oracle and Java are registered trademarks of Oracle and/or its affiliates.</p>
<p>The Apache NetBeans website conforms to the <a href="https://privacy.apache.org/policies/privacy-policy-public.html">Apache Software Foundation Privacy Policy</a></p>
</div>
</div>
</div>
<script src="../../../../_/js/vendor/lunr.js"></script>
<script src="../../../../_/js/search-ui.js" id="search-ui-script" data-site-root-path="../../../.." data-snippet-length="100" data-stylesheet="../../../../_/css/search.css"></script>
<script async src="../../../../search-index.js"></script>
<script src="../../../../_/js/vendor/jquery.min.js"></script>
<script src="../../../../_/js/vendor/what-input.min.js"></script>
<script src="../../../../_/js/vendor/foundation.min.js"></script>
<script src="../../../../_/js/vendor/jquery.colorbox-min.js"></script>
<script src="../../../../_/js/netbeans.js"></script>
<script>
$(function(){ $(document).foundation(); });
</script>
<script src="../../../../_/js/vendor/highlight.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el);
});
});
</script>
</body>
</html>