X

An Oracle blog about Data Visualizations

Recent Posts

JDeveloper and ADF 12.2.1.1.0 Released With New Visualization Features

JDeveloper and ADF 12.2.1.1.0 are now available for download on Oracle Technology Network. Even though this is a patchset release on top of 12.2.1.0 (released last October), we are happy to report that there are a number of new Data Visualization features that made their way to ADF from JET Data Visualizations. New visualization: Picto Chart uses discrete icons to visualize an absolute number or relative sizes. It is extensively used in infographics as a more interesting and effective way to present numerical information than traditional tables and lists. Read more about PictoChart in ADF in this doc chapter. New visualization: Tag Cloud provides visual representation for text data, typically used to visualize free form text or tag metadata for a website. Read more abut Tag Cloud in this doc chapter. New Chart type: Stock Chart is useful for displaying information about a stock on a time axis. Unique to stock charts is the candlestick series which allows for displaying open, close, high, low information for the stock price. Read more about Stock Chart in ADF in this doc chapter. Range Series Type: Range area and range bar charts help visualize data sets with varying low/high values (doc link). Hierarchical labels can now be used to display hierarchical data on the categorical axis charts (doc link) Chart Axis now supports logarithmic axis scale. Drilling can now be enabled on the chart data items, series, and groups. This causes a drill event to be fired when the user performs the drill interaction. The application can listen to this event to update the chart with the appropriate drilled data. Ability to individually style the categorical axis labels allows for emphasizing specific groups, which is a lot more useful than styling the labels as a whole. Tooltips are now also supported for categorical axis labels. A number of enhancements are now supported in Gauge components: Status Meter Gauge: Ability to specify border and color for plot area, string title, corner radius and border, displaying indicator wider than the plot area (doc link) Circular Status Meter Gauge: Ability to control the radius, start angle and angle extent Support for human shapes for Rating Gauge and Led Gauge Vertical orientation for Rating Gauge You can read about other new features in JDeveloper and key themes for the release in this post by Shay Shmeltzer and the New Features document, and play with the ADF Faces Rich Client demo to learn more about the new features in ADF Faces and Data Visualization components.

JDeveloper and ADF 12.2.1.1.0 are now available for download on Oracle Technology Network. Even though this is a patchset release on top of 12.2.1.0 (released last October), we are happy to report...

New Data Visualization Features in JET 2.0.1

Oracle JET 2.0.1 was released on April 18th and includes the following new data visualization features: Custom Center Content for Donut Chart Custom center content is now supported for donut chart. This allows arbitrary HTML content to be specified through a knockout template or a JavaScript renderer. Custom Center Content for Circular Status Meter Gauge Custom center content is now supported for circular status meter gauge. This allows arbitrary HTML content to be specified through a knockout template or a JavaScript renderer. Custom Marker Shapes and Images Custom marker shapes and images are now supported in Chart, Diagram, NBox, and Thematic Map. Support was added for Picto Chart, LED Gauge, and Rating Gauge in the v2.0.0 release, and this feature is now available for all applicable data visualizations. Bar Chart Rendering Performance Performance has been improved for large data sets. The chart has also been enhanced to better deal with large numbers of series, especially for bar charts. Thematic Map Automatic Marker Sizing Thematic Map now supports automatic sizing of markers whose relative size is specified through the new value property.This is similar to the support in bubble charts, making it much easier to configure markers for responsive layouts. NBox Custom Count Labels A custom count label can now be specified for each NBox cell, allowing the application to display total number and percentage of markers in the cell, which is especially useful for overflow cases. Other Enhancements Chart: Tooltip and converter support has been added to the donut chart center label. Tag Cloud: A color attribute is now supported on tag cloud items, providing a convenience API that is consistent with data items in other components. Thematic Map: Thematic Map tooltips can now be customized for regions that aren't associated with data. Overview and best practices for Data Visualizations in JET is provided in the JET Data Visualizations FAQ. For more information visit Oracle JET website, and post your questions on Oracle JET forum.

Oracle JET 2.0.1 was released on April 18th and includes the following new data visualization features: Custom Center Content for Donut Chart Customcenter content is now supported for donut chart. This...

New Data Visualization Features in Oracle MAF 2.3

Oracle Mobile Application Framework 2.3 release is now available and contains a number of new features, including support for Windows platform and built-in integration with MCS Analytics. Consult this blog article for a complete list of new features. The new Data Visualization features include: Range Charts: Range area and range bar charts help visualize datasets with varying low/high values. Hierarchical labels can now be used to display hierarchical data on the categorical axis charts. For more details about hierarchical labels, please see this blog article on the Oracle JET blog. Ability to individually style the categorical axis labels allows for emphasizing specific groups, which is a lot more useful than styling the labels as a whole. Tooltips are now also supported for categorical axis labels. Standalone legend can now be used with shared attribute groups to display colors consistently across data visualization components. This helps with achieving one of the primary best practices related to using multiple data visualizations, which is that all components should consistently represent the data and that they should behave as a cohesive dashboard rather than a set of independent components. Support for specifying labels and label styles for markers on the GeographicMap component A number of enhancements are now supported in Gauge components: Status Meter Gauge: Ability to specify border and color for plot area, string title, corner radius and border, displaying indicator wider than the plot area Circular Status Meter Gauge: Ability to control the radius, start angle and angle extent Support for human shapes for Rating Gauge and Led Gauge Vertical orientation for Rating Gauge For more details on Gauge configuration consult JET blog articles Introduction to Gauges Part 1: Status Meter Options and Best Practices and Introduction to Gauges Part 2: Circular Status Meter.

Oracle Mobile Application Framework 2.3 release is now available and contains a number of new features, including support for Windows platform and built-in integration with MCS Analytics. Consult this...

Oracle JET 2.0.0: Now Available Open Source with New Data Visualization Features

Oracle JET 2.0.0 was just released and is now available as open source on GitHub! JET 2.0.0 includes a number of new Data Visualization features, including: Picto ChartA new PictoChart visualization lets the user visualize numeric values using images. Common in infographics, this component provides a more interesting and effective way to present numerical information than traditional tables and lists. The JET PictoChart supports the same animation and interactivity features as our other visualizations, including selection, highlighting, and filtering, and we think it will be an essential ingredient in producing compelling dashboards. For an in-depth look at PictoChart, read this JET blog article: Introduction to PictoChart. New Charting Features New charting features include: Ability to zoom and scroll the chart only in one direction Ability to display total count for the bar in stacked bar chart Ability to wrap label text on chart axis labels Ability to display different data series and chart type in chart "zoom & scroll" window. Support for categories on reference objects, allowing the reference objects to participate in the highlighting and filtering across data visualizations There are many more new data visualization and framework features in JET 2.0.0. For a complete list of new features, read the blog article "What's New in Oracle JET 2.0.0" and consult the JET release notes. For a series of in-depth articles on JET Data Visualizations consult JET Data Visualizations FAQ.

Oracle JET 2.0.0 was just released and is now available as open source on GitHub! JET 2.0.0 includes a number of new Data Visualization features, including: Picto ChartA new PictoChart visualization...

Customizing Tile Size in Masonry Layout

Masonry Layout is a new layout that displays its contents in a grid, like a dashboard. It was introduced in ADF 12.2.1, MAF 2.2, and JET 1.1.2.This article focuses on customizing the masonry layout tile sizes in ADF. In ADF, masonry layout can take any ADF Faces component as a child, respectively called a tile. Tiles can span columns and rows. When the UI is provided, users can insert, delete, reorder and resize the tiles. When the available display space changes, the masonry layout rearranges the tiles to fit into the new display size. In this blog post and video, Shay Shmeltzer shows how to use masonry layout in JDeveloper 12.2.1. As mentioned in the video, masonry layout uses built in styleClasses for the size of masonry tiles. The style class names are in the format of AFMasonryTileSize1x1 with support for the following tile sizes: 1x1, 1x2, 1x3, 2x1, 2x2, 2x3, 3x1, and 3x2. One of the questions frequently asked by the customers of this layout is how do we change the default size of the tiles? Answer: The application can customize card sizes per instance of the masonryLayout through skinning.  The application developer can define card sizes to be different based on additional app-defined style classes.  For example, the application developer could define a different set of card sizes when the "AppSmall" style class is applied to the masonryLayout:  .AppSmall .AFMasonryTileSize1x1 {    width: 100px;    height: 100px;    margin: 5px;  }  .AppSmall .AFMasonryTileSize2x1 {    width: 210px;    height: 100px;    margin: 5px;  }  ..and so on Then, in the jspx page, the application developer would use the following code:  <af:masonryLayout id="ml1" styleClass="AppSmall">    <af:panelGroupLayout id="pgl1" styleClass="AFMasonryTileSize1x1">    </af:panelGroupLayout>  </af:masonryLayout> Please note that the app must define a complete set of AFMasonryTileSize*x* style classes for all column and row spans so that all sizes are consistent within the set for each instance of the masonryLayout.   For more information, please consult the chapter "Displaying Contents in a Dynamic Grid Using a masonryLayout Component" in the "Organizing Content on Web Pages" section of Fusion Middleware Guide to Developing User Interfaces with Oracle ADF Faces. We also recommend to look at code samples for Masonry Layout and Masonry Layout Behavior in the hosted ADF Faces 12c Component Demo.

Masonry Layout isa new layout that displays its contents in a grid, like a dashboard. It was introduced in ADF 12.2.1, MAF 2.2, and JET 1.1.2.This article focuses on customizing the masonry layout...

Chart Tips: Coloring by Group and Displaying Attribute Groups in the Legend

We often get questions from customers on how to configure chart colors. The JET blog article How to Create Colorful Bar Charts explains very well how to configure chart colors in JET. In this blog article we will explain how to configure chart colors in ADF. In a previous blog post we talked about displaying overview window on the charts and coloring by groups. In this post you will learn more about attribute groups and how to display them in the chart legend. Using the data from the sample WorkBetter application (source code available here), let's create a new bar chart displaying average compensation by department. In JDeveloper 12.2.1, create a new jsf page and drag and drop the departments collection into the page. Note the new Chart design time appears when you choose to create a Chart: The new charting design time UI provides the ability for an end user to view a dynamic chart sample while binding data to various sections of the chart. The users are now able to drag attributes from the available list to the chart X, Y axis or legend area and get immediate feedback in the form of the dynamic chart sample. To create our chart, drag the attribute avgTotalComp to the Y Axis (Bars) section, and drag the attribute deptName to the X Axis section. The code for the new chart looks like this: <dvt:barChart orientation="vertical" id="barChart1" var="row"              value="#{bindings.departments.collectionModel}">     <f:facet name="dataStamp">              <dvt:chartDataItem id="di1"                   value="#{row.avgTotalComp}" series="Departments" group="#{row.deptName}">     </dvt:chartDataItem>     </f:facet> </dvt:barChart> By default, the bar for each department is displayed in blue, which is the first color in the DVT Alta skin. A popular request from our customers is to display each bar in different color. As explained before in the previous Chart Tips formatting blog post, an easy way to do this is to specify an attribute group to color the data by group. To create an attribute group, in the Structure Window locate the dvt:chartDataItem tag, right click on it and chose Insert Inside Chart Data Item -> Attribute Groups. On the new attribute group tag, set the type to color and the value to vary by row.deptName. This will assign distinct color to each bar representing a department.The attribute groups tag should look like this: <dvt:attributeGroups id="ag1" type="color" value="#{row.deptName}"/> When we run the page, the chart displays each bar in a different color from the built-in Alta palette, but the chart legend still displays only one series color for Departments: In order for the attribute groups to display in the legend, we need to insert a dvt:legendSection tag into the dvt:chartLegend tag. In the Structure window, right-click on the dvt:chartLegend tag and choose Insert Inside Chart Legend -> Legend Section. Using the Property Inspector, set the source property of the dvt:legendSection to ag1, which is the id for the attribute group we created earlier. This tells the legend section to pull its data for the attribute group. Our chart code should now look like this: <dvt:barChart orientation="vertical" id="barChart1" var="row"               value="#{bindings.departments.collectionModel}">      <dvt:chartLegend id="cl1">           <dvt:legendSection id="ls1" source="ag1"/>      </dvt:chartLegend>      <f:facet name="dataStamp">               <dvt:chartDataItem id="di1" value="#{row.avgTotalComp}" series="Departments" group="#{row.deptName}">                    <dvt:attributeGroups id="ag1" type="color" value="#{row.deptName}"/>               </dvt:chartDataItem>      </f:facet></dvt:barChart> Run the page again, and notice how the legend is now populated and each department is represented with a different color in the legend. However, the legend item "Departments" is still appearing: In order to hide the "Departments" legend item, we can add a dvt:chartSeriesStyle tag and specify that this series item should be hidden: <f:facet name="seriesStamp">     <dvt:chartSeriesStyle series="Departments" displayInLegend="off" id="css1"/></f:facet>  Please note that displaying colors in both the X axis labels and in the legend does not make much sense. If you would like to turn off the X Axis and tick labels, you could do so with the following code: <dvt:chartXAxis id="cxa1">     <dvt:chartTickLabel rendered="false" id="ctl1"/>     <dvt:majorTick rendered="false" id="mt1"/></dvt:chartXAxis> The final chart code is given below: <dvt:barChart orientation="vertical" id="barChart1" var="row"              value="#{bindings.departments.collectionModel}" barGapRatio="0.2">     <dvt:chartLegend id="cl1">          <dvt:legendSection id="ls1" source="ag1"/>      </dvt:chartLegend>     <f:facet name="dataStamp">              <dvt:chartDataItem id="di1"                    value="#{row.avgTotalComp}"                    group="#{row.deptName}"                    series="Departments">                    <dvt:attributeGroups id="ag1" type="color" value="#{row.deptName}"/>               </dvt:chartDataItem>     </f:facet>     <f:facet name="seriesStamp">              <dvt:chartSeriesStyle series="Departments" displayInLegend="off" id="css1"/>     </f:facet>      <dvt:chartXAxis id="cxa1">          <dvt:chartTickLabel rendered="false" id="ctl1"/>          <dvt:majorTick rendered="false" id="mt1"/>     </dvt:chartXAxis> </dvt:barChart> Here is our final bar chart: Note that there is an even simpler way of  specifying the department data so that each bar is displayed in a different color. When creating the data binding for the bar chart, simply drag the avgTotalComp field to the X axis and drag the deptName to the Y Axis (Bars) area: If you would like to turn off the group label, us the same code as above to turn off the XAxis labels. The final chart code looks like this: <dvt:barChart orientation="vertical" id="barChart1" var="row"              value="#{bindings.departments.collectionModel}" barGapRatio="0.2">     <f:facet name="dataStamp">              <dvt:chartDataItem id="di1" series="#{row.deptName}" value="#{row.avgTotalComp}"                                       group="Average Total Compensation"> </dvt:chartDataItem>     </f:facet>     <dvt:chartXAxis id="cxa1">          <dvt:chartTickLabel rendered="false" id="ctl1"/>           <dvt:majorTick rendered="false" id="mt1"/>     </dvt:chartXAxis></dvt:barChart> The generated bar chart will look like this: In this use case each department is shown as a series of only one group. However, we can't control the spacing between the bars representing the departments, which is often requested by customers, so this is why we recommend the first approach where each bar is represented in its own group. We hope that you found this post helpful, and as always, we welcome your feedback!

We often get questions from customers on how to configure chart colors. The JET blog article How to Create Colorful Bar Charts explains very well how to configure chart colors in JET. In this blog...

Oracle OpenWorld 2015: JET and Data Visualizations

There were many great sessions and announcements at Oracle OpenWorld 2015, but for me the most exciting was the announcement of Oracle Javascript Extension Toolkit (JET). Oracle JET is our new development framework, targeted at intermediate to advanced JavaScript developers working on client-side applications. It's a collection of open source JavaScript libraries along with a set of Oracle contributed JavaScript libraries that make it as simple and efficient as possible to build applications that consume and interact with Oracle products and services, especially Oracle Cloud Services. JET was formally announced by our VP Chris Tonas in his general session: Revolutionizing Application Development with Oracle Cloud on Tuesday, October 27th. Chris showed how a business user ("citizen developer") can use Oracle Application Builder Cloud Service to connect to data from Oracle Sales Cloud and develop a custom application without writing any code. He talked about how this application can then further be extended by developing a custom component in JET using Developer Cloud. For this session we developed a demo in JET using our Data Visualization components to show a sales forecasting scenario. Brian Fry (ABCS and Tools PM) showed how a developer can edit code in Developer Cloud, and then Chris showed how to bring this custom forecasting UI back into Application Builder Cloud Service. Chris explained how with the introduction of JET we now provide the right technology for the right person: There were several great sessions focused solely on JET by JET PM John Brock (JB) and Netbeans/JET PM Geertjan Wielenga. I attended their session on Wednesday: Embracing JavaScript: Experience the New Oracle JavaScript Extension Toolkit [CON8091] in which JB gave an overview of JET and showed all the great collateral that is now available on the JET website, including an overview of the JET cookbook and how to use it to learn to code in JET. Geertjan showed a great demo of Oracle JET plugin for Netbeans, which he also described in this blog article. Another session that was nicely attended was Oracle Alta UI Design: Implementing Oracle’s Best Practices in Your Applications [CON8296] presented by Laura Akel (Alta/ADF/MAX PM) and Richard Wright (UX). Laura and Richard explained how the Alta UI is the unifying theme across our UI frameworks: ADF, JET, and MAF. Laura gave a great demo of our sample WorkBetter application that was designed and built to showcase the Oracle Alta UI. She showed the latest features in MAF 2.2.0, ADF 12.2.1 and JET v1.1.2. Richard talked about the updated Oracle Alta UI site, the Alta guidelines, and the key principles of implementing an Alta UI. Our data visualization session: Creating Stunning, Mobile-First User Interfaces with Oracle Data Visualizations [CON8185] that was presented by Hugh Zhang, Jairam Ramanathan (JET/DVT development managers) and myself was also heavily focused on JET. We started by giving an introduction to JET and showing the forecasting demo from Chris Tonas's general session in more detail. Jairam Ramanathan (JET/DVT development manager) showed a new demo which we called Data Visualization Explorer. He used a data set about popular programming languages that Chris also talked about in his general session, and a data set about basketball, which tied well into Thomas Kurian's keynote.He talked about the importance of choosing the right visualization, sharing colors across components, and mentioned how new Oracle Data Visualizations Cloud Service (announced during Larry Ellison's and Thomas Kurian's keynotes) uses our data visualization and the JET framework, which is also the case with the latest Enterprise Manager Cloud services.Jairam than handed over to Hugh Zhang (JET/DVT development manager), who showed how to get started with JET quick start template. He showed first how to write a simpler example in JET with a gauge and two-way binding, and then showed how to set up associated views with highlighting. Hugh then showed the JET website and data visualization examples in the JET cookbook, and how one can change the code in cookbook examples and see the changes right away. We concluded our session by talking about the new Data Visualizations features in ADF 12.2.1 and MAF 2.2.0. which were just released, and how we can now easily expose functionality across development frameworks because we have a shared layer in Oracle Data Visualizations. Hands-On Labs JB and Geertjan held two hands-on labs: Getting Started with Oracle JavaScript Extension Toolkit, which were both full. The hands-on lab script teaches you how to get started with Oracle JET using NetBeans IDE 8.1. The full script for the hands-on labs is available on the JET website here. Development Tools PMs Shay Shmeltzer, Laura Akel, and I held a hands-on lab titled Build Responsive Web Applications with Oracle ADF [HOL10380], which focused on using the new masonry layout and data visualization features in ADF 12.2.1. This lab was also very well attended and we received many requests for the script. Demogrounds We had many customers visit us at the demogrounds for Application Development Framework, Mobile Application Framework, and JET that were next to each other. JET booth had a lot of interest, and we had great representation at the booth by JET development (Amy Dai, Jairam and Hugh) along with our PM team. Below is a photo of John Brock (JB) JET PM and Katarina Obradovic-Sarkic (author of this post) at the JET demogrounds booth. Laura Akel (Alta/ADF/MAX PM) talking to Oracle Ace Director Lucas Jellema of AMIS at the ADF Faces booth: On one end of the Moscone South demogrounds there were showcase booths, which were an even better way to present to customers. Here is a photo of Denis Tyrell, Mobile and Tools PM Director, demoing how to build an application with Mobile Application Accelerator (MAX), part of the Mobile Cloud Service (not yet released) at the Mobile Showcase booth: Leave us a comment if you are looking for any materials that we presented at OpenWorld and hope to see you again next year!

There were many great sessions and announcements at Oracle OpenWorld 2015, but for me the most exciting was the announcement of Oracle Javascript Extension Toolkit (JET). Oracle JET is our new...

New Data Visualization Features in JDeveloper and ADF 12.2.1

JDeveloper and ADF 12.2.1 is now available for download on Oracle Technology Network. The following new features have been introduced in the UI layer: Alta Skin is now enabled by default in all the ADF Faces and Data Visualization components. Alta skin is an essential component of the new Oracle Alta UI design system. For more information on Oracle Alta UI please refer to the newly redesigned Alta design patterns website. Masonry Layout is a new layout that displays its contents in a grid, like a dashboard. It can take any ADF Faces component as a child, respectively called a tile. Tiles can span columns and rows. When the UI is provided, users can insert, delete, reorder and resize the tiles. When the available display space changes, the masonry layout rearranges the tiles to fit into the new display size. New Data Visualization Component: NBox is used to visualize and compare data across two dimensions. It is commonly used to visualize and compare employee performance. A new data-binding dialog at design time for the NBox component is also available. Pie Chart Enhancements:The innerRadius attribute on the Pie Chart lets the users create a "donut" chart look. There are also new attributes to control pie slice gaps, label positioning, and using pie slice explosion as a selection effect. Funnel Chart has replaced a now deprecated Funnel Graph. Funnel charts are typically used to visualize a process where the different sections of the funnel represent different stages in the process, for example stages in a sales cycle. Polar coordinate system: Several Chart types now support a new coordinateSystem attribute that specifies if the chart uses Cartesian or Polar coordinates. A polar chart has a radial y-axis and a tangential x-axis. Polar coordinate system can be used for bar, line, area, combination, scatter, and bubble charts. Polygonal grid shape (commonly known as "radar") is supported for polar line and area charts. Polar charts are recommended for directional data. (e.g. air drag vs. boat angle) Polar charts are also recommended for categorical data where all categories are equally important. (e.g performance appraisal categories) Below are examples of Polar Bar and Polar Line Charts. Polar line has a polygonal shape grid also known as radar chart:  Here are examples of scatter and bubble polar charts: Thematic Map - Map Provider feature allows Thematic Map to be configured to retrieve geographic data from any data source through the MapProvider APIs, including Oracle eLocation services.The MapProvider APIs  allow the custom basemap to be configured and treated like a built-in basemap with all the same functionality including drilling, short/long labels, custom region supprt, pointLocation projections, etc. New Charting Design Time UI provides the ability for an end user to view a dynamic chart sample while binding data to various sections of the chart. New NBox design time is now available: The Diagram visualization, available since 12.1.3 release, now has support for design-time creation and data-binding: You can read about other new features in JDeveloper and key themes for the release in this post by Shay Shmeltzer and the New Features document, and play with the ADF Faces Rich Client demo to learn more about the new features in ADF Faces and Data Visualization components.

JDeveloper and ADF 12.2.1 is now available for download on Oracle Technology Network. The following new features have been introduced in the UI layer: Alta Skin is now enabled by default in all theADF...

Visit Us at OpenWorld 2015!

If you are coming to Oracle OpenWorld and JavaOne this year, here is a list of sessions and hands-on labs related to Data Visualization in our frameworks and tools that we don't want you to miss. OpenWorld Conference Sessions General Session: Revolutionizing Application Development with Oracle Cloud [GEN9500] is going to be presented by our VP Chris Tonas on Tuesday at 11am in Moscone South - 103. The following Conference Sessions are all going to be in Moscone South: Oracle Alta UI Design: Implementing Oracle’s Best Practices in Your Applications [CON8296], Monday, 1:30pm, Room 274 Don’t Develop—Compose Your Mobile Applications Easily with Oracle Mobile Cloud Service [CON9489], Tuesday, 4pm, Room 270 Next-Generation JavaScript, REST, and HTML5 Development with Oracle [CON8469], Tuesday 4pm, Room 304 Meet the Experts: Oracle’s Development Tools and Frameworks [MTE10022], Tuesday, 6pm, Room 300 Embracing JavaScript: Experience the New Oracle JavaScript Extension Toolkit [CON8091], Wednesday, 12:15pm, Room 304 Our session below has Data Visualization as the primary focus: Creating Stunning, Mobile-First User Interfaces with Oracle Data Visualizations [CON8185], Wednesday, 4:15pm, Room 304 JavaOne Conference Sessions The following sessions will be presented at JavaOne: HTML5 and JavaScript Clients in an Enterprise Application World [CON7767], Tuesday, 11am,  Hilton - Imperial Ballroom B Coding for Desktop and Mobile with HTML5 and Java EE 7 [CON7773], Tuesday, 5:30pm,  Hilton - Yosemite A/B/C Hands-On Labs The following hands on labs focus on Data Visualizations in our different frameworks and are both located in Hotel Nikko - Nikko Ballroom III (3rd Floor): Build Responsive Web Applications with Oracle ADF [HOL10380], Monday, 5pm Getting Started with Oracle JavaScript Extension Toolkit [HOL10407], Wednesday, 8:45 am and Thursday, 12:30pm Demo Grounds Visit us at at the following demo booths in the Fusion Middleware Demogrounds: Application Development Framework/Mobile Application Framework Oracle JavaScript Extension Toolkit See a complete list of development tools and frameworks sessions here. We are looking forward to seeing you there!

If you are coming to Oracle OpenWorld and JavaOne this year, here is a list of sessions and hands-on labs related to Data Visualization in our frameworks and tools that we don't want you to miss. OpenWo...

Data Visualizations at Visualizing Information Design Jam

Oracle Data Visualizations were featured in a great Oracle event organized by Laurie Pattison and our colleagues at the AppsUX innovation team: The goal of this event was to bring together different teams within Oracle, and with a lot of help and guidance from the UX team, think about how to make our product more visually engaging and come up with ideas for new visualizations. In preparation for this event we did several training sessions, one of which was my presentation on what are the opportunities to use data visualizations and how to choose your visualization techniques. Laurie did a great session on the process for designing a data visualization, starting with thinking about who your users are and what are the business problems they are trying to address. Read her blog post A Data Visualization Design Approach on this topic at the Apps UX Innovation Events blog. Donna Scheele presented on how to create visually engaging UIs using Alta concepts and also blogged about this topic on the Middleware UX blog. 16 teams across Fusion Apps, Middleware and Database participated in the event. All teams came prepared with a business problem they were trying to solve in the form of an elevator pitch.  Mentors were available to work with teams in advance to solidify the pitch into something actionable that could be reasonably be accomplished in less than two days. Given that they only had 3 minutes to present at the end of the jam, both mentors and judges reviewed the pitches in detail in advance for the appropriate context.The design jam started with a design workshop given by visual design and data visualization experts in AppsUX, John Cartan and Julia Blyumen. After this 3 hour workshop, the participants were ready to start designing, and they only had a little more than a day to come up with their new design. To find out more about the event and the winning designs, read this report on the event by Laurie Pattison on the Apps UX Innovation Events Blog. Mentors (from left to right): Julia Blyumen, Katy Massucco, John Cartan, from AppsUX, me (Katia Obradovic-Sarkic, DVT), Laurie Pattison (blog), Erika Webb (AppsUX), Soraya Younossi, Donna Scheele (blog) from Middleware UX, Serguei Orozco, Mindi Cummins (AppsUX). The Visualizing Information Design Jam was a great success and many teams came up with new designs that we will hopefully see in the Oracle products soon. 

Oracle Data Visualizations were featured in a great Oracle event organized by Laurie Pattison and our colleagues at the AppsUX innovation team: The goal of this event was to bring together different...

Charts Tips: Zoom and Scroll with the Overview Window, Colors using Attribute Groups

The new Charts introduced in ADF 12.1.3 and MAF 2.0.x offer superior performance and user experience, including: Client-side layout and interactivity Redesigned zoom and scroll Marquee zoom and selection Redesigned Time axis Improved data labeling Did you know how to turn on the overview window for zooming and scrolling, like shown in the image above? Let's take you through some simple steps to enable zooming and scrolling and the overview window. Assuming you created a simple bar chart displaying employee salaries, to enable zooming and scrolling, in the Property Inspector under the Behavior section, set the zoomAndScroll to live. Setting the zoomAndScroll property to "live" enables scrolling on the Chart using a thin scrollbar, but does not enable the full overview window. To enable the display of the overview window, you need to insert the overview facet on the Chart: Next, insert the dvt:overview tag into the overview facet: Run the page and test your new zoom and scroll overview window: If you would like to make the bar colors alternate using the built-in Alta color styles, insert the dvt:attributeGroups tag and set the type to color. <dvt:attributeGroups id="ag1" type="color" value="#{row.LastName}" /> The attribute groups value varies by row.lastName, which means that each bar displaying employee salaries by last name will be rendered in different color: Our employee salary chart is now displayed with a set of built-in Alta colors and with the zooming and scrolling overview window enabled.

The new Charts introduced in ADF 12.1.3 and MAF 2.0.x offer superior performance and user experience, including: Client-side layout and interactivity Redesigned zoom and scroll Marquee zoom and selection R...

A Guide to Diagram – Part 11 - Selected Node Information

Once you start to work with the diagram there is a natural desire to move on from the visualisation aspects into interactivity. This raises the basic question: If I have an event handler on a node, how can I get information about that node?  The pattern for doing this is simple but it's a good topic to cover.  When you click a node to the diagram it updates the selectedRowKeySet associated with the diagramNodes (the same is true for the diagramLinks as well), so when you need to access the selected node this is the place to look.  As a simple example of this we might have a popup menu associated with your nodes: <dvt:diagramNode  ...>  <af:showPopupBehavior popupId="::nodemenupopup" triggerType="contextMenu" align="endAfter"/>  And then a menu item wired to a listener: <af:commandMenuItem text="Operate on node" actionListener="#{diagramHelper.nodeMenuOpListener}"/>  So in the listener all you need to do is to obtain the handle to the diagramNodes object and call getSelectedRowKeys on that: RowKeySet keys = getRuleDiagramNodes().getSelectedRowKeys(); In this case the getRuleDiagramNodes() method returns the UIDiagramNodes reference created by defining the standard binding attribute in the <dvt:diagramNodes> tag to inject it's reference into this managed bean. Once you have the RowKeySet, you can either iterate through it's entries or convert it to an array and access the key value. Once you have the key, then you can look up the underlying object that the node represents from your model, and from there, access any of the attributes that you need.

Once you start to work with the diagram there is a natural desire to move on from the visualisation aspects into interactivity. This raises the basic question: If I have an event handler on a node,...

A Guide to Diagram – Part 10 - Inter-Group Links

If you create a diagram that contains groups (containers) there are some special considerations to take into account when writing your layouts. These relate to the use of links that traverse the containers, specifically those which have an origin or destination inside of a container. For example you have something like this: Figure 1 - Basic inter-group links In this situation your layouts have to be somewhat aware of this cross container linking and how they will be presented with the information that will be needed to correctly route your links.  When you have links such as those shown in Figure 1 and you collapse the containers, the diagram will create a special link which represents a roll-up or "summary" of the links that run between the two containers.  This is represented as a dashed line: Figure 2 - Collapsed Groups showing Links If you hover the mouse over this link it will then provide you with information about the number of  "real" links that it represents. When you build your layouts for diagram you are responsible for routing this summary link in just the same way as you would any other link, and on top of this special rules apply when one or more of the groups are expanded. This process can be a little confusing at first, so I thought that it would be a good example for an article in the diagram series: Setting up  If you want to follow along here, create yourself a new Workspace for an ADF Fusion Project and create a new Java class from this code.  This just creates a very basic set of nodes and links that I'll use to drive this example. Once you have created the class, expose it as a view scope managed bean called diagramModel that we can then use. In summary this model defines two sets of nodes.  Two grouping nodes each with two children.  There are then links between the corresponding children in each group, as per Figure 1.  The actual diagram definition on the page is really quite simple in this case: <dvt:diagram id="d1" layout="alignedLayoutHorizontal"                     summary="Demonstration diagram to show cross container links"                     emptyText="No data to show"                      controlPanelBehavior="initCollapsed"> <dvt:clientLayout name="alignedLayoutHorizontal" method="DemoDiagramLayouts.coreAlignedLayout" featureName="DemoDiagramLayouts"> <f:attribute name="alignment" value="horizontal"/> </dvt:clientLayout> <dvt:clientLayout name="alignedLayoutVertical" method="DemoDiagramLayouts.coreAlignedLayout" featureName="DemoDiagramLayouts"> <f:attribute name="alignment" value="vertical"/> </dvt:clientLayout> <dvt:diagramNodes value="#{viewScope.diagramModel.nodes}"  var="node" id="dn1"> <dvt:diagramNode id="dn_tg" nodeId="#{node.nodeId}"  containerId="#{node.containerId}" layout="alignedLayoutVertical"  showNodeActions="false" > <f:facet name="zoom100"> <dvt:marker id="nodeMarker" height="80" width="80" borderColor="#000000" borderStyle="solid" borderWidth="1.0" labelDisplay="on" value="#{node.label}"> <dvt:attributeGroups id="typeGroup" type="color shape" value="#{node.nodeType}"> <dvt:attributeMatchRule id="typeG" group="G"> <f:attribute name="color" value="#EAEAEA"/> <f:attribute name="shape" value="rectangle"/> </dvt:attributeMatchRule> <dvt:attributeMatchRule id="typeN" group="N"> <f:attribute name="color" value="red"/> <f:attribute name="shape" value="circle"/> </dvt:attributeMatchRule> </dvt:attributeGroups> </dvt:marker>   </f:facet> <f:facet name="containerBottom"> <af:outputText value="#{node.label}" id="ot1"/> </f:facet> </dvt:diagramNode> </dvt:diagramNodes> <dvt:diagramLinks value="#{viewScope.diagramModel.links}" var="link" id="dl1"> <dvt:diagramLink id="ln1" startNode="#{link.startId}"  endNode="#{link.endId}"  endConnectorType="arrow"  linkStyle="solid"  linkWidth="3"/>                   </dvt:diagramLinks>                                              </dvt:diagram> Layouts There are two layouts defined by the code: alignedLayoutHorizontal which is the top level layout used by the diagram itself and alignedLayoutVertical which is used by the only node definition.  The effect of these layouts are that the top level group nodes in the diagram will display side by side and then any nodes inside of the top level nodes will use a vertical arrangement. If you look a little more closely though, you will see that both clientLayout definitions actually point to the same JavaScript routine called coreAlignedLayout passing an attribute called alignment to control how that operates. If we just concentrate on the part of the layout that handles the links it looks like this in the first version, the version where we don't take the containers into account (You will be able to read the full source code for the layout by following a link at the end of this article): ...//Layout the links - loop in the normal wayvar linkCount = layoutContext.getLinkCount();for (var j = 0;j < linkCount;j++) { var layoutLink = layoutContext.getLinkByIndex(j); DemoDiagramLayouts._routeLink(layoutLink,layoutContext, alignment);}...   So all this code does is to loop through each of the links for this layout instance and call the _routeLink routine to do the work.  Here's the initial version of the _routeLink code that produced Figure 2. As you can see, in that case, it positioned the links nicely;vertically centered on the correct edge of the start node and connecting to the corresponding point on the destination: _routeLink: function (routeLink, layoutContext, alignment) {  var sourceNode = layoutContext.getNodeById(routeLink.getStartId());  var destNode = layoutContext.getNodeById(routeLink.getEndId());  var sourceNodePos = sourceNode.getPosition();  var destNodePos = destNode.getPosition();  var sourceNodeDims = sourceNode.getContentBounds();  var destNodeDims = destNode.getContentBounds();  var points = [];  if (alignment == "horizontal"){    if (sourceNodePos.x < destNodePos.x){      points.push(sourceNodePos.x + sourceNodeDims.w + routeLink.getStartConnectorOffset());      points.push(sourceNodePos.y + (sourceNodeDims.w/2));      points.push(destNodePos.x - routeLink.getEndConnectorOffset());      points.push(destNodePos.y + (destNodeDims.w/2));    } else {      points.push(sourceNodePos.x - routeLink.getStartConnectorOffset());      points.push(sourceNodePos.y + (sourceNodeDims.w/2));      points.push(destNodePos.x + destNodeDims.w + routeLink.getEndConnectorOffset());      points.push(destNodePos.y + (destNodeDims.w/2));    }  } else { //vertical    if (sourceNodePos.y < destNodePos.y){      points.push(sourceNodePos.x + (sourceNodeDims.w /2 ));      points.push(sourceNodePos.y + sourceNodeDims.h + routeLink.getStartConnectorOffset());      points.push(destNodePos.x + (destNodeDims.w/2));      points.push(destNodePos.y - routeLink.getEndConnectorOffset());      } else {        points.push(sourceNodePos.x + (sourceNodeDims.w/2));        points.push(sourceNodePos.y  - routeLink.getStartConnectorOffset());        points.push(destNodePos.x + (destNodeDims.w/2));       points.push(destNodePos.y + destNodeDims.h + routeLink.getEndConnectorOffset());    }      }  routeLink.setPoints(points);} So that all seems to work. However, if we expand the first group we get this: Figure 3 - First Group Expanded It's sort of OK, the edges connect to the second group correctly but there is some overlap between the endpoints in the first group and the nodes. Notice as well that at this point that the inter group links are still show as dashed because the actual source and destination nodes within Group 2 are not yet visible.  So we then expand Group 2: Figure 4 - Both Groups Expanded Notice how the links are now rendered as the correct solid lines, and the vertical links that happen within the groups are just fine.  However, the inter-group links that should be joining 1 to 3 and 4 to 2 have gone very, very wrong. Why is that?  Understanding the Problem In order to really understand what's going on here you have to appreciate how diagram handles multiple layouts and how different layouts are responsible for different links.  In this simple case, when we have two open containers on the page, the layout engine will be called three times. The diagram works from the inside out, so the innermost layouts (those for Group 1 and Group 2 respectively) will be processed before the final top level layout.  If you step through the layout code in this case you would see the alignedLayoutVertical being processed for each of those. Interestingly, as you do so you will also see that each of those layout routines only has to handle one link. When Group 1 is processed the only link to handle will be the one that starts at Child 2 and ends at Child 1 and in the case of Group 2 its the link between Child 3 and Child 4. Because the links between Child 1 and 3  and Child 4 and 2 are not wholly contained within the same container they have to be processed by their mutual parent, which in this case is the top level layout. Once the two inner layouts are done, then the overall diagram layout (alignedLayoutHorizontal) will be called to layout the two container nodes. It is this layout that will be handed the two inter-group layouts as nodes and the links between the,.  So that's the first rule to remember: Rule 1 - Cross container links are routed by the closest layout run that contains both the source and the destination nodes. The second factor is the relative coordinate systems of each layout. When you write layout code, you work to a standardized layout system relative to the top left hand origin of a virtual canvas at 0, 0.  Now within your layout, you are quite at liberty to place objects at any coordinate, positive or negative relative to this origin, by convention we start at 0,0 for convenience.  The way to think about this is that once a layout is complete, the diagram will logically draw the smallest rectangle that it can around the nodes and links that you have drawn and and crop out  any whitespace beyond this boundary. This rectangle now represents a single node (remember that a container layout runs before it's parent) and now when the parent layout is called, it will be passed this container node which is sized according to this cropped rectangle (assuming it is expanded of course).  The parent layout can now tell how to layout these nodes as the size of each will now be known. So now we're laying out the parent layout and, according to Rule 1 above, we know that it will be the parent layout will be handled the two inter-container links to route. Now when we route a link, we generally find out the locations and dimensions of the start and end nodes, so that we know where to anchor the link.  So we get the ID of the start or end node and call layoutContext.findNodeById() using that ID. Just as I've done in the code above, and as shown here: var sourceNode = layoutContext.getNodeById(routeLink.getStartId()); We can then ask that node for it's location using the getPosition() API.  And here's the problem which leads to: Rule 2 - A node always reports its position relative to its own layout container.   A node knows nothing of where it actually is, outside of it's own layout context. So for example a node may have been positioned at 10,10 in it's own layout, but that layout itself may have been positioned at 20,20 by the parent layout.  The result is that the actual location of the node is 30,30 on the final canvas. Dealing with Node Layout Relative Coordinates So this is the mistake that my first attempt at the layout exhibits.  It uses the position of the node as reported by that node, rather than the position in terms of the parent layout that is running.  To solve this, we first need to identify if the node is inside of a container, and if so, convert its position from this local frame of reference to the global system being used by the current layout.  So the first problem is to check if the source or destination nodes for the links are within a container. We can do this by calling the getContainerId() function on the node.  If it returns a result, we know that we need to rebase the node position to the correct coordinate origins. The way to do this rebasing task, is to call a separate API on the layoutContext called localToGlobal(). This API takes two arguments, a point location and a node. The node argument identifies the node that we want the coordinates of in global terms, the point argument is an offset from that.  We usually just pass DvtPoint(0,0) to this argument to indicate that we're interested in the location of the top left hand corner of the node in question. So here's the amended code for the link routine with this simple change in place and highlighed for you: _routeLink: function (routeLink, layoutContext, alignment) { var sourceNode = layoutContext.getNodeById(routeLink.getStartId());  var destNode = layoutContext.getNodeById(routeLink.getEndId());  var sourceNodePos = sourceNode.getPosition();  var destNodePos = destNode.getPosition();    //See if we need to handle a cross container link  var nodeTopLeft = new DvtPoint(0,0);  if (sourceNode.getContainerId()){    sourceNodePos = layoutContext.localToGlobal(nodeTopLeft,sourceNode);   }  if (destNode.getContainerId()){    destNodePos = layoutContext.localToGlobal(nodeTopLeft,destNode);     }  var sourceNodeDims = sourceNode.getContentBounds();  var destNodeDims = destNode.getContentBounds();  var points = [];  if (alignment == "horizontal"){    if (sourceNodePos.x < destNodePos.x){      points.push(sourceNodePos.x + sourceNodeDims.w + routeLink.getStartConnectorOffset());      points.push(sourceNodePos.y + (sourceNodeDims.w/2));      points.push(destNodePos.x - routeLink.getEndConnectorOffset());      points.push(destNodePos.y + (destNodeDims.w/2));    } else {      points.push(sourceNodePos.x - routeLink.getStartConnectorOffset());    points.push(sourceNodePos.y + (sourceNodeDims.w/2));      points.push(destNodePos.x + destNodeDims.w + routeLink.getEndConnectorOffset());      points.push(destNodePos.y + (destNodeDims.w/2));    }  } else { //vertical    if (sourceNodePos.y < destNodePos.y){      points.push(sourceNodePos.x + (sourceNodeDims.w /2 ));      points.push(sourceNodePos.y + sourceNodeDims.h + routeLink.getStartConnectorOffset());      points.push(destNodePos.x + (destNodeDims.w/2));      points.push(destNodePos.y - routeLink.getEndConnectorOffset());    } else {      points.push(sourceNodePos.x + (sourceNodeDims.w/2));      points.push(sourceNodePos.y  - routeLink.getStartConnectorOffset());    points.push(destNodePos.x + (destNodeDims.w/2));      points.push(destNodePos.y + destNodeDims.h + routeLink.getEndConnectorOffset());    }      }  routeLink.setPoints(points);} That then will be enough to correct the coordinates and fix up the links to the version that we see in Figure 1. More Complex Cases In the case that I've discussed in this example we have a simple two level diagram, where a node is either at the top level, or ir is inside a single container.  Of course diagrams might be more complicated than this and, for example, multiple levels of containership could be used.  In that case, just checking for a containerId on the node will not be enough to see if you have a cross container link.  In that case you will need to cross reference the nodeIds presented by the link, with the list of nodes being handled by this particular layout. A second interesting use case is if you want to route the roll-up links in a different way from conventional links.  These links are handed to the layout in the normal way but you can identify them by testing the isPromoted() method on the link object itself. If either the source, destination or both terminating nodes for the link are hidden within a collapsed container then this flag will be set to true.  The full source code for the fixed layout JavaScript can be found here.  

If you create a diagram that contains groups (containers) there are some special considerations to take into account when writing your layouts. These relate to the use of links that traverse the...

Controlling Your Diagram Viewport

When you start to build your own diagrams you may be wondering how to control the "initial" view of the diagram inside of the component.  By default, the initial view that you see will be sized correctly to see the entirety of the diagram - all nodes will be visible.  However, what if you need more control? Well there are two approaches you can take, the first a simple declarative approach and the second which involves your layout code. Looking at the simple approach first.  If you look at the diagramNodes component you will see a property called centerRowKey. This property can be set to an EL expression which needs to evaluate to the rowKey of the node that you want to center on - typically you can use this in combination with node selection (see: Guide to Diagram Part 11- Selected Node Information) to allow a user to re-focus the diagram to the clicked node.   Need More Control?Now centerRowKey is perfectly suitable for most situations, however, what if you need more control?  An example of this might be where you want to start the view of the diagram off in a zoomed state - just focusing on a particular subset of nodes for example.  Fortunately there are a  couple of JavaScript APIs that you can call from your layout code that come in handy here.  The getComponentSize() function on the layoutContext.  This returns a DvtDiagramRectangle object which encodes the base width and the height of the diagram component. Note, however, that the logical size of the diagram may be smaller / different from this depending on it's shape relative to the  component The setViewport( DvtDiagramRectangle) function, also on the layoutContext.  Both of these use DvtDiagramRectangle which is an object with the properties .x,.y,.w and .h, you can hopefully guess what each of those properties holds! A new DvyDiagramRectangle object can be created using the code: var vp = new DvtDiagramRectangle(xpos, ypos,  width, height)  For the task in hand, the setViewport() function is what we are interested in. You can think of it as drawing a scaled rectangle over the entirety of the diagram. If you proportionally reduce the size of the viewport then that will zoom in on the diagram. So you use the width and height attributes of the DvtDiagramRectangle that you pass to control the scaling, and then the x and y position to place the zoomed viewport relative to the base diagram.  For example - lets say I want to zoom into the centre of a diagram that is defined as  a rectangle diagRect, I would use: layoutContext.setViewport(new DvtDiagramRectangle((diagRec.w/4), (diagRect.h/4), (diagRect.w/2), (diagRec.h/2))); Alternatively the following would apply the same zoom level but show the top left hand quadrant of the diagram: layoutContext.setViewport(new DvtDiagramRectangle((diagRec.w/2), 0, (diagRect.w/2), (diagRec.h/2))); The one thing to watch out for here is not to assume that the  rectangle returned by getComponentSize is actually the size of your diagram, it is not.  It provides the basic size in pixels of the physical diagram component.  The diagram (nodes and links) itself is sized based on your layout and then scaled to provide a best fit in the available space in that physical component. Accordingly if you want to set the viewport, it pays to keep track of how wide and high your diagram actually grows to as you add nodes and links.  You can then work out the scaling factor that will have to be used to "fit" that into the physical component and then you will have the information that you need to manipulate the view port.

When you start to build your own diagrams you may be wondering how to control the "initial" view of the diagram inside of the component.  By default, the initial view that you see will be sized...

Data Visualizations at Oracle OpenWorld 2014

This year at OpenWorld the Oracle Data Visualizations had a strong representation with two DVT focused sessions, two hands-on labs, and our visualizations featured across the board in Thomas Kurian's keynote, Chris Tonas' general session, several MAF sessions, and a number of sessions that featured DVT in our internal customer products. We also had a strong presence from the DVT development team with Hugh Zhang, Amy Dai, and Jairam Ramanathan who did a great job co-presenting with Duncan Mills and myself on our two DVT sessions. Oracle Alta UI One of the most exciting announcements from our point of view was the launch of Oracle Alta UI in Chris Tonas's General Session: Next-Generation Application Development—The Mobile and Cloud Effect. Oracle Alta UI is not just a new skin, it is a new approach for designing modern UIs for Mobile, Cloud and Web applications. The key points of Oracle Alta UI are: designing for mobile platforms first, responsive layout, and clean and simplified look that emphasizes key information using Data Visualizations. Oracle Alta UI resources are now available at http://bit.ly/oraclealta. We published a set of design patterns and provided demos based on an HR scenario called WorkBetter demo for Mobile Application Framework and ADF. Our ADF Faces WorkBetter demo is hosted here. Here are photos of our VP Chris Tonas demoing the WorkBetter Faces application, a showcase app for the new Oracle Alta UI. In the photos below, our VP Chris Tonas is demonstrating the responsive layout features by resizing the browser which causes our page layout to switch from horizontal to vertical. The Info Tiles switch to display in a vertical column and the DVT Timeline switches its display to vertical.  DVT Focused Sessions On Monday Jairam and Duncan presented a session titled Diagram-Based UIs in Oracle ADF: A Giant Leap Forward, featuring a lot of great Diagram demos and sample code, including a new demo on how to progressively build a Sankey diagram by Jairam. We had more than  80 customers attending this session, and a lot of interest after the session. Our general DVT session: The Picture That Paints a Thousand Words: Data Visualization on Web and Mobile was on Wednesday, presented by Hugh Zhang, Amy Dai, and myself. We had very good attendance with 78 people in the audience. We started with an overview of DVT components, relationship with Oracle Alta UI, use cases and internal customers, including demos Election Across Components and Election Across Time. I then introduced and gave demos of the new components: Diagram and NBox. Hugh then took over giving an overview of our new Charting solution, demos of the upcoming Chart features and roadmap. Amy took over to present the latest features in Thematic Map, and then demoed some of our upcoming features, including DVT mashups, to a great delight by the audience. We concluded by pointing the customers to our collateral, DVT blog, WorkBetter app samples and hands-on labs which were scheduled after our session. Related Sessions It was fortunate that our session was scheduled right after Laura Akel (PM) and Richard Wright (UX)'s session:Modern UI Design: Implementing Oracle’s Best Practices in Your Applications which focused on the Oracle Alta UI and implementation of the WorkBetter Alta sample in ADF Faces. That session was standing room only and there was a lot of interest from customers in the new Oracle Alta UI and related sample applications. Another great session for Data Visualizations was Building Performant Mobile Apps with Amazing UIs, Using Oracle Mobile Application Framework, presented by our PM Director Denis Tyrell and MAF PM Srini Indla on Wednesday afternoon. This session covered tips and tricks and best practices for building highly performant mobile apps with really cool UIs, using Oracle Mobile Application Framework and featured some examples from the Work Better demo for MAF. DVT hands-on labs  Developing Web and Mobile Dashboards with Oracle ADF were hosted by Frank Nimphius and myself in two time slots and were very well attended. Attendees learned how to create a dashboard page with ADF Faces, create a chart, change the bar colors and turn on zooming and scrolling via overview window, then create a circular status meter gauge, sunburst, Hierarchy Viewer, and Thematic Map. If you attended one of our labs and did not get to finish it, you can download the materials here. You can download the slides for of all our ADF and MAF sessions at OOW here. To find the slides, click on the session you are interested in and look under "Presentation Download". Drop us a note if you have any questions about Oracle Data Visualizations at OOW and we hope to see you next year!

This year at OpenWorld the Oracle Data Visualizations had a strong representation with two DVT focused sessions, two hands-on labs, and our visualizations featured across the board in Thomas Kurian'ske...

A Guide to Diagram – Part 9 – Attribute Groups and Node Stacking

In Part 8 of this series I showed how nodes could be grouped together inside of a container node. This can provide a very effective way of organizing your diagram to allow progressive disclosure of large amounts of data and of course it is a very good way to plot hierarchical data sets. In some data sets though, you have large numbers of nodes at the same level from a hierarchical perspective, but would like to be able to selectively filter or otherwise distinguish between sets of nodes.  This is where attribute groups come in. Understanding Attribute Groups  Attribute groups are a way of varying the look of nodes of the same type based on some underlying property of the node contents. Effectively this allows you to group nodes with a shared property value in a visual manner without having to write complex expression language or define multiple node definitions.  As an example, I've made a slight change to the Node definition that this series has been using to add a status attribute to the nodes and this will have one of three values "Planned", "In Progress" or "Complete", I can then use an attribute group to categorize the nodes on the diagram using that property as the grouping factor. (I've reverted to the flat node model with just 5 per nodes here) And here's the modified diagramNode definition: <dvt:diagramNodes id="dns1"                   value="#{diagramModel.nodes}"                   var="node">  <dvt:diagramNode id="dn1"                    nodeId="#{node.uniqueNodeId}"                    label="#{node.nodeLabel}">    <f:facet name="zoom100">      <dvt:marker id="nodeMarker"                   height="80" width="80"                   shape="circle"                  borderColor="#000000"                   borderStyle="solid"                   borderWidth="1.0">        <dvt:attributeGroups id="statusGroup"                              type="color"                              value="#{node.status}"                             label="#{node.status}"/>        </dvt:marker>    </f:facet>  </dvt:diagramNode></dvt:diagramNodes> Notice the following about this version of the code: I've removed the fillColor from the marker, this is now provided by the attributeGroup The status attribute of the node is passed as the value of the attributeGroup, this is the grouping value.  (I also set the label attribute as well which we'll discuss in a moment)  As well as varying by color you can also vary the fill pattern, x scaling and y scaling or even several attributes together using a space delimited list type="color pattern": Controlling the Assignments You'll notice that when I varied the color (and indeed the pattern), nowhere did I specify the "pool" of color options to be used or the order.  The default behavior here is actually defined in the skin being used (see the tagdoc on <dvt:attributeGroups> for that ).  You can, however, explicitly control things within a specific diagram, using the <dvt:attributeMatchRule> and <dvt:attributeExceptionRule> tags.  Using the match rule I can assign specific colors to each different value for status: <dvt:marker id="nodeMarker"             height="80" width="80" shape="circle"             borderColor="#000000" borderStyle="solid" borderWidth="1.0">  <dvt:attributeGroups id="statusGroup"                        type="color"                        value="#{node.status}"                       label="#{node.status}">    <dvt:attributeMatchRule id="statPln" group="Pending">      <f:attribute name="color" value="red"/>    </dvt:attributeMatchRule>        <dvt:attributeMatchRule id="statIn" group="In Progress">      <f:attribute name="color" value="yellow"/>    </dvt:attributeMatchRule>        <dvt:attributeMatchRule id="statComp" group="Complete">      <f:attribute name="color" value="green"/>    </dvt:attributeMatchRule>      </dvt:attributeGroups>                     </dvt:marker> This results in the control I need: The <dvt:attributeExceptionRule> tag can be used in a similar way except rather than explicitly matching a value, it takes an expression in its condition property that can be evaluated using information from the current node to apply the property or not. Using the Legend One advantage of using attributeGroups for node formatting is that also integrates the diagram into the  <dvt:legend> component.  The legend appears in the top right of the diagram, optionally as a slide-out box, although it can be fixed as well shoudl you desire: The legend is nested within the <dvt:diagram> tag thus: <dvt:legend disclosed="false"      label="Legend">  <dvt:showLegendGroup label="Current Status">    <dvt:legendSection source="dns1:statusGroup"/>  </dvt:showLegendGroup></dvt:legend> The source attribute on the legendSection points to the relative id of the attributeGroups tag.  When the legendSection is rendered the label used for each entry corresponds to the label property defined within the attributeGroups tag. Functionality Added by the Legend    The legend not only provides a visual key for the diagram, but can also be used as a filter to control the display of whole groups of nodes at once.  The user can click on the entry inside of the legend to toggle the display of that class or group of nodes. Here I've filtered the diagram to hide the nodes marked as "Completed": As you hide or display groups of nodes using the Legend, the diagram will animate in an appropriate fashion. Note that if you want to add this kind of filtering functionality to the diagram, then your layouts will need to be fairly forgiving and be able to cope with nodes being hidden and displayed.  Stacking Nodes A final feature of nodes that use attributeGroups is that you can use the grouping to "stack" all the nodes of the same type into a pile.  Such a pile (from a different diagram) would look like this: The number 16 overlaid on top of the node indicates how many nodes are in the "stack". When you have a stack of nodes like this, you can either preview the contents of the stack using the preview icon that appears when you select the stack: This will pop an overlay on top of the current diagram with a simple folder-style (you have no control of the layout) view of the nodes in the stack: Or, you can also select the unstack option: To un-stack the nodes into the diagram itself.  Naturally you can re-stack in a similar way. Enabling Stacking In order to use node stacking, you do of course need to be using attributeGroups, but in addition to this you need to reference the id of the attributeGroup that you want to use to stack by using the groupBy property on the <dvt:diagramNodes> tag.  The diagram will initially display with the nodes stacked.  Design Considerations when using Stacking Be aware of the following minor points: You have no control of the actual stacking order.  Generally the first node within the nodes collection that represents a particular group will be the one displayed on the top of the stack, but you have no explicit control over this other than that ordering.  When links are rendered between stacks on the diagram they essentially represent a union of all the defined links between individual nodes within those stacks.  As a result your layout will be passed generated "summary" links which will not, for example, have any label information (as that would make no sense).  Therefore any layout code that may be used in a stacked node scenario should be prepared for a null result from any call to getLabelBounds() on the link. Code defensively in your layout code for this scenario.   In the Next Article Now that we have covered most of the visual and layout aspects of diagram it's time to look how your diagram can be decorated with a little interactivity.  I'll start off in the next article which will talk about the definition of pop-ups on various artifacts within the diagram.

In Part 8 of this series I showed how nodes could be grouped together inside of a container node. This can provide a very effective way of organizing your diagram to allow progressive disclosure of...

A Guide to Diagram – Part 8 – Diagram Container Groups

So far we've been looking at simple diagrams with a single array of related nodes. Even this simple setup affords many possibilities for representing data in interesting ways. We can, however, add a whole new dimension to the diagram using containers.   Container Grouping Data Model As the name suggests we need to add some form of grouping relationship into the data mode.  The approach that is taken is one of a hierarchical relationship between nodes.  Thus nodes that share the same parent are grouped together logically under that parent.  For the sake of illustration, let's go back to the running example that we've been working with so far and add an optional attribute that will reference the node ID of a node's parent. I've also added a new constructor to create a parented node:  public class SampleNode {  private int _uniqueNodeId;  private String _nodeLabel;  private int _preferredColumn;  private int _parentNodeId = -1; //-1 means no parent in this case  public SampleNode(int id, String label, int column) {    _uniqueNodeId = id;    _nodeLabel = label;    _preferredColumn = column;  }  public SampleNode(int id, String label, int column, int parent) {    this(id, label, column);    _parentNodeId = parent;  }  public int getUniqueNodeId() {    return _uniqueNodeId;  }  public String getNodeLabel() {    return _nodeLabel;  }  public int getPreferredColumn() {    return _preferredColumn;  }  public int getParentNodeId() {    return _parentNodeId;  }} And change the main model class to add some parented nodes using the new constructor.  public DiagramDataModel(){  _nodes = new ArrayList<SampleNode>(10);  _nodes.add(new SampleNode(0,"First Node",0));  _nodes.add(new SampleNode(1,"Second Node",0));  _nodes.add(new SampleNode(2,"Third Node",2));  _nodes.add(new SampleNode(3,"Fourth Node",2));  _nodes.add(new SampleNode(4,"Fifth Node",1));   //Add some child nodes for Second Node and Forth Node  _nodes.add(new SampleNode(5,"Second Node Child 1",0,1));  _nodes.add(new SampleNode(6,"Second Node Child 2",0,1));  _nodes.add(new SampleNode(7,"Fourth Node Child 1",0,3));  _nodes.add(new SampleNode(8,"Fourth Node Child 2",0,3));  _nodes.add(new SampleNode(9,"Fourth Node Child 3",0,3));  _links = new ArrayList<SampleLink>(8);  _links.add(new SampleLink(0,1,1,"PLANNED","Alpha"));  _links.add(new SampleLink(1,2,1,"PLANNED","Beta"));  _links.add(new SampleLink(2,3,1,"PLANNED","Gamma"));    _links.add(new SampleLink(3,4,1,"PLANNED","Delta"));    _links.add(new SampleLink(4,0,1,"COMPLETE","Epsilon"));    //and links between the new child nodes  _links.add(new SampleLink(5,6,1,"PLANNED","Group 1 A"));    _links.add(new SampleLink(7,8,1,"PLANNED","Group 2 A"));    _links.add(new SampleLink(8,9,1,"PLANNED","Group 2 B"));    } Having made that change, if I run the diagram again I just see the new nodes laid out in the first column below the other nodes: The Grouping UI So let's actually take advantage of the new parent / child structure in the UI.  To do this, all we need to do is set the containerId attribute on the <dvt:diagramNode> to be a non-null value which the diagram will use to locate the parent. Here's the amended node definition: <dvt:diagramNode id="dn1"                  nodeId="#{node.uniqueNodeId}"                   containerId="#{node.parentNodeId > -1?node.parentNodeId:null}"                 label="#{node.nodeLabel}" >  <f:facet name="zoom100">    <dvt:marker fillColor="#ff0000"                 height="80" width="80" shape="circle"                 borderColor="#000000" borderStyle="solid"                 borderWidth="1.0" />  </f:facet></dvt:diagramNode> Note how I'm using a ternary expression in the containerId to only use it when there is a valid parent. You can use this EL based approach or, create a separate node definition to apply to containees controlled by the rendered property. With the containership established the diagram looks a little different, you can see in the screenshot below how nodes "Second Node" and "Fourth Node" have gained the expand icon (highlighted with an arrow): The user can then click the plus icon to expand the group in place: Note the following: When the node ("Second node") is expanded we now see the containees, and the second node is now displayed as a simple box with a close indicator in the top left corner The layout of the diagram as a whole has changed slightly. Notice that the gap between the node and label for "First Node" is much larger.  This is an artifact of the layout using the widest node metrics to determine this spacing.  The widest node is now the expanded "Second Node". So if your diagram will include groups then you need to consider this. Because we calculated the endpoints of the links in the layout based on the source and destination nodes, the link between the first and second nodes is still anchored correctly to the middle of the opposing edges, even though it means that the orientation of the link is no longer vertical. But I Don't Like / Want that Plus (Expand) Symbol! The icon that the diagram puts into the top left of the node to expand the container is an optional thing.  You can suppress its display using the showDisclose property on the diagramNode:   showDisclose="false"  When the expand symbol has been hidden using this option, the user can still drill into the node using the drill icon that appears when you click the node, although that will reduce the display to just the focused container and hide the other nodes.  (You can also hide this drill behavior by using the showDrill property) You can also programmatically control the disclosure of the node using the disclosedRowKeys property of the diagramNodes tag. So, for example, you might want all of the containers to start out expanded rather than closed, or you might want your to use your own gestures to control expanding and collapsing rather than the default expand icon.  The disclosedRowKeys collection makes all this possible. Group Specific Facets Going back to the article on node contents, I mentioned  that there were some container related facets. So now is a good time to cover those. Background Facet Although the background facet can be used for any normal node, it more usually comes into play in the context of a container. It's job is to fill the background on the container node when expanded.  In this example I have assigned a background facet thus: <f:facet name="background">  <dvt:marker fillColor="#FF0000" opacity="0.1"               height="80" width="80"               shape="circle" borderStyle="none"/></f:facet> Normally this would be hidden behind the Zoom100 marker, however, when the container is expanded this is the effect: Note how I've reduced the opacity on the background marker to ensure that the child nodes remain readable. Notice, as well, how the marker SVG is stretched to completely fill the container. If you need padding, then you'll have to include that into the SVG image you use. Container Background Styling  I'll note at this point, that you do not have to use the background facet to control how the body of an expanded container looks. You can also apply basic CSS style information using  the containerStyle property of the diagramNode. So if all you want to do is color the background of the container, this would be the approach to take. If you have suppressed the default disclosure mechanism using showDisclose=false, then you will not get the default boarder around the whole node and so the containerStyle will allow you to set your own border styling in this case as well. containerTop/Bottom/Start/End/Left/Right Facets This set of facets all do the same thing, allowing you to define more content inside of the expanded group container in the assigned position.  Within these facets you can place the same types of content as you might use in a zoom facet.  So for example I could do something like this: <f:facet name="containerTop">  <af:panelGroupLayout layout="horizontal" valign="middle">    <af:spacer width="25"/>    <dvt:marker fillColor="#FF0000"                 height="20" width="20"                 shape="circle" borderStyle="none" />    <af:spacer width="10"/>             <af:outputText value="#{node.nodeLabel}"/>  </af:panelGroupLayout></f:facet> This results in a sort of "header" to be shown in the expanded node, but normally invisible: The actual "content" area of the container node is separate from the container layout facets so the child nodes will not overlap anything that you place on them.  These layout facets do, however, overlay the content of the background facet (which will always fill the node).  Container Nodes and Layouts In the screenshots above we see that the child nodes within the container are laid out vertically, just like the top level nodes in the diagram.  This is the default behavior, however, it does not have to be this way.  When we first started looking at this sample (In Part 1 of the series), I alluded to the fact that you could define more than one clientLayout tag within the <dvt:diagram>.  The top level diagram tag only has a single layout attribute which will define this overall default, however, each <dvt:diagramNode> tag also has a layout attribute that can be used to specify that a particular layout should be used if this node happens to end up being an expanded container.  To illustrate this I've created a second horizontal linear layout and added that to the LearningDiagramLayouts script. This is then assigned to the layout property of the stamped diagramNode. So we now have two layouts defined, with learningVerticalInColumns being applied to the diagram as a whole and learningHorizontal being applied to any expanded container nodes: <dvt:diagram id="d1" summary="Example Diagram"             layout="learningVerticalInColumns">  <dvt:clientLayout name="learningVerticalInColumns"                    method="LearningDiagramLayouts.columnVertical"                    featureName="LearningDiagramLayouts">    <f:attribute name="columns" value="2"/>    <f:attribute name="columnWidth" value="50"/>    <dvt:nodeAttributes node="dn1">      <f:attribute name="displayColumn"                    value="#{'preferredColumn'}"/>    </dvt:nodeAttributes>  </dvt:clientLayout>       <dvt:clientLayout name="learningHorizontal"                     method="LearningDiagramLayouts.simpleHorizontal"                    featureName="LearningDiagramLayouts"/>  <dvt:diagramNodes id="dns1"                     value="#{diagramModel.nodes}" var="node">    <dvt:diagramNode id="dn1" nodeId="#{node.uniqueNodeId}"                       containerId="#{node.parentNodeId > -1?node.parentNodeId:null}"                     label="#{node.nodeLabel}"                      layout="learningHorizontal">... Here's the result: How Container Layouts are Processed In the example above, we have two layout functions and, as the diagram is rendered, the correct function will be called to layout each container. This means that the simpleHorizontal function layout will be called twice to sort out the content nodes of Second Node and Fourth Node respectively and then columnVertical function will be called to layout the top level diagram. It's important to understand that each layout is called in isolation and the list of links and nodes passed by the layoutContext; getNodeCount(), getLinkCount(), getNodeByIndex() and getLinkByIndex(), is confined to those specific to this container. Because the innermost layouts are done first, the node metrics that the container node receives will reflect the space allocated to correctly layout the containee nodes.  Inter-Layout Links The final twist with containers and layouts is the question of how to handle links that join nodes that are not peers in the same container, i.e. those that cross container boundaries.  The layout code that we have dealt with so far has all be relative to the container being laid out, so APIs like getPosition() on the node return a DvtPoint object that returns those relative coordinates. The solution to this problem lies with the localToGlobal() API on the layoutContext.  This function takes a local coordinate in the context of a particular node and returns a global coordinate value that, when used in the context of the base relative coordinate system, will correctly transform the target point when the layout is complete. To help you to understand if you need to use this API, you can call the getContainerId() API on the node for both the start and end nodes to see if the two nodes are being handled by separate layouts.  In the Next Article Now that we have covered groups of nodes in containers we will finish off working with groups of nodes by looking at attributeGroups and the node stacking functionality. 

So far we've been looking at simple diagrams with a single array of related nodes. Even this simple setup affords many possibilities for representing data in interesting ways. We can, however, add a...

A Guide to Diagram – Part 7 – Configurable Layouts

In the previous three parts in this series on <dvt:diagram> I've introduced the mechanics of laying out your nodes and links using a JavaScript layout function.  As we've seen, we can introduce some flexibility through intelligent use of the available node and label sizing metrics, however, in this article I want to explore how you can go one step further and pass contextual information into the JavaScript function to make the layout itself configurable and, possibly more importantly, make the layout sensitive to the actual data that is being represented. Providing Layout Level Configuration Let's start out with exploring how you can pass configuration information into the diagram as a whole. To continue in the theme of the previous articles, I'll take the example LearningDiagramLayouts.simpleVertical() layout function and build on a version of that. I've called this new layout LearningDiagramLayouts.columnVertical and you'll find it linked at the end of the article for reference. To make things a little more interesting I've added a couple more nodes to the data model and altered the node size. Here's the starting point, you'll notice that the existing (simpleVertical) layout handled the extra nodes and different sizing without a problem, so that's a good start. As a next step, to enhance this diagram, I want to be able to stagger the nodes into virtual columns so that the information can be displayed in a smaller amount of vertical space. However, rather than just creating a layout to produce say a two-column view and then a separate third layout for a three-column view, the aim is to create a single adaptable layout that can be configured for any number of columns and then lay the nodes out in reading order. Here's the end result (as with the previous examples this is a purely illustrative layout, I'm not claiming at it will be useful): That will then be further extended to make the virtual column width configurable as well: In technical terms, the loop that positions the nodes now has to calculate a x position for the node rather than always setting that to zero as we did before. This is accomplished using two variables in the function, virtualColumns, and virtualColumnsWidth. for (var i = 0;i < nodeCount;i++) { var node = layoutContext.getNodeByIndex(i); ...  xPos = ((i)%virtualColumns) * virtualColumnWidth;  node.setPosition(new DvtDiagramPoint(xPos, yPos)); ... So, how do we pass the values for virtualColumns and  virtualColumnWidth into the JavaScript? Let's look at that. Layout Attributes The good news is that passing layout configuration attributes like this is really easy to do.  To pass values into a layout, all you need to do is to nest <f:attribute> tags inside of the existing <dvt:clientLayoutTag> in your page. For example: <dvt:clientLayout name="learningVerticalInColumns" method="LearningDiagramLayouts.columnVertical"                  featureName="LearningDiagramLayouts">   <f:attribute name="columns" value="3"/>   <f:attribute name="columnWidth" value="100"/></dvt:clientLayout>                  You can supply literal values as I have here (3 and 100 respectively), or use expression language.  Then, in your JavaScript, these values can be obtained from the layoutContext using the getLayoutAttributes() API referring to the same names that were supplied to <f:attribute>:     ...    var virtualColumns = 2;    var virtualColumnWidth = 100;    if (layoutContext.getLayoutAttributes()) {      if (layoutContext.getLayoutAttributes()["columns"]) {      virtualColumns = parseFloat(layoutContext.getLayoutAttributes()["columns"]);      }      if (layoutContext.getLayoutAttributes()["columnWidth"]) {      virtualColumnWidth = parseFloat(layoutContext.getLayoutAttributes()["columnWidth"]);      }    }    ... You'll notice here that I have defined a sensible set of default values for the settings, this is to ensure that the parameters are effectively optional for the developer.  Additionally, when passing numeric values in as attributes to a layout you must be sure to use the parseInt() and parseFloat() JavaScript functions to ensure the correct datatype is received.  Node Level Attributes The attributes that I've used so far, are global to the layout, but what if you want to control the diagram to a much finer level?  Generally this will mean passing information that will be needed in the context of an individual node.  To do this, you extend your use of the <dvt:clientLayout>, and nest within it, an additional tag called <dvt:nodeAttributes>.  The nodeAttributes tag takes a node component id in its node attribute.  This will correspond to the JSF id attribute on one of the <dvt:diagramNode> tags nested within the diagram.  So if you have multiple node type definitions within your diagram you will need to configure the additional attributes for each one.  This gives you the flexibility to pass different contextual information to different node types. Within the nodeAttributes tag you then have a series of <f:attribute> children.  To illustrate this I've extended the datamodel that we've been using so far, to add a new attribute called preferredColumn to the SampleNode.java object.  This is the value that we want to pass down into the layout. Here's the new definition for the Java SampleNode object: public class SampleNode { private int _uniqueNodeId;  private String _nodeLabel;  private int _preferredColumn;  public SampleNode(int id, String label, int column){  _uniqueNodeId = id;    _nodeLabel = label;    _preferredColumn = column;  }  public int getUniqueNodeId() {  return _uniqueNodeId;  }  public String getNodeLabel() {    return _nodeLabel;  }  public int getPreferredColumn() {    return _preferredColumn;  }} Now to pass that new bit of information into the layout. The clientLayout definition now looks like this: <dvt:diagram id="d1" summary="Example Diagram" layout="learningVerticalInColumns"> <dvt:clientLayout name="learningVerticalInColumns" method="LearningDiagramLayouts.columnVertical"                    featureName="LearningDiagramLayouts">   <f:attribute name="columns" value="3"/>   <f:attribute name="columnWidth" value="200"/>   <dvt:nodeAttributes node="dn1">    <f:attribute name="displayColumn" value="preferredColumn"/>   </dvt:nodeAttributes>  </dvt:clientLayout> You'll notice that the <f:attribute> tag has a value attribute set to the name of the property in the node object. This value is not supplied as an EL expression. It directly names the property in the underlying model object.  As such, the usage of <f:attribute> for the main layout is slightly different from this usage embedded within a nodeAttributes, it passes by reference, not value. You cannot pass hardcoded or EL based values through the value property, although if your EL resolves correctly to the name of an attribute in the underlying model you're OK.  Accessing Node Level Attributes in JavaScript The process for accessing a node level attribute in JavaScript  is much the same as for the top level layout attributes. The node object exposes a getLayoutAttributes() API that works in just the same way.  So we can update our node-positioning loop slightly to use a passed in column hint: for (var i = 0;i < nodeCount;i++) { var node = layoutContext.getNodeByIndex(i);  ...  //Set a default value   var candidateColumn = (i) % virtualColumns;  //Check to see if the node asks for a different column  if (node.getLayoutAttributes()) {    if (node.getLayoutAttributes()["displayColumn"]) {      candidateColumn = parseInt(node.getLayoutAttributes()["displayColumn"]);    }  }  xPos = candidateColumn * virtualColumnWidth;  node.setPosition(new DvtDiagramPoint(xPos, yPos)); ... And this results in an even more flexible layout with a swim-lane like effect based on the passed in preferences (In this case nodes First and Second ask for column 0, Third and Forth for column 2 and Fifth for column 1): The Power of Node Level Layout Attributes Node level layout attributes allow you to effectively extend the logical model in JavaScript for a particular node and make layout-positioning decisions based on that extended model.  Using them means that you are no longer a slave to the iteration order of the nodes as they are delivered to you in the getNodes() array. In an extreme example you could even pass the desired x and y coordinates into the layout with the node, and effectively store the layout in your server side model rather than re-calculating it. The Full JavaScript Source Now that we have developed a second layout for this columnVertical example, I've linked the source for that here.  In the Next Article Over the last seven articles I've covered the core artifacts and principles of layouts within diagram.  The next topic builds on many of the concepts that you've already read about and dives into node groups.

In the previous three parts in this series on <dvt:diagram> I've introduced the mechanics of laying out your nodes and links using a JavaScript layout function.  As we've seen, we can introduce some...

A Guide to Diagram – Part 6 – Advanced Links

In the last article in this series I covered the basics of link routing and showed how the setPoints() API for a link could be used to create a non-straight line path between two nodes, as shown here: In this article I want to look at some of the more advanced ways of managing links, covering: Label rotation Curved links Label Rotation In the layout above, one nice enhancement would be to have the label for the Gamma link rotated to follow the direction of the link, thus: To do this we have a new API to play with; setLabelRotationAngle() (note that a node has these same APIs as well) .  This API takes a rotation angle in radians.  The rotation itself will take place around the point defined by another API: setLabelRotationPoint().  This takes an x,y coordinate in the form of a DvtDiagramPoint object and defines the rotation point in the context of the label boundaries, so 0,0 for example is the top left corner of the label.  Therefore you use setLabelPosition() API to define the gross position of the label on the diagram and then the other 2 APIs to control the angle and point of rotation.  Here's the sample code used to position the Gamma label and rotate it. Note that if you are rotating from the top-left corner of the label as I am doing here, there is no need to explicitly set the label rotation point as that defaults to 0,0. Refer back to the code sample from the previous article for the context in which you will find this fragment:   linkLabelXPos = turn3.x - (link.getLabelBounds().h + 5);  linkLabelYPos = linkStartPos.y + ((linkEndPos.y - linkStartPos.y) / 2)       + (link.getLabelBounds().w / 2);  // rotate to 270 degrees  link.setLabelRotationAngle(270 * (Math.PI / 180));  ...         link.setLabelPosition(new DvtDiagramPoint(linkLabelXPos, linkLabelYPos)); Curved and Complex Links Sharp angles aren't for everyone, in some layouts you may want to have nice curves (or a mix). For example, we might want to change the sample to look like this: Here things get a little more complicated and you will have to step beyond basic JavaScript knowledge.  If you've been following along through the whole series of articles you may recall that I revealed that SVG is used as the underlying rendering technology for the diagram.  That knowledge comes in handy now, as it turns out that links are simply SVG path elements.  As such, we can apply the same SVG notation to draw a curved link path in diagram. To do this, instead of passing a simple array of x and y coordinates to setPoints() as a path we can use an array like this: (I've replaced the variables you would actually use with literal values to make things clearer): link.setPoints(["M",10,144,"C",-97,247,-97,-107,10,-4]); In this case the "M" and the "C" mark the start of the line [M] and a cubic Bezier curve [C] definition respectively.  The M element is followed by the x and y values for the start position of the path.  The C element takes 3 pairs of coordinates, the first two are the control points for the Bezier curve and the final pair is the termination point: Link paths themselves can be simple like this single cubic curve, or they can be constructed from multiple elements appended together. The core elements that you can use to create these more complex paths are: Prefix Arguments Purpose M A single pair of coordinates. e.g["M",0,0] Defines the start point of a complex curve, in this case at position x=0,y=0 L A single pair of coordinates. e.g[M,0,0,"L",10,20] Draws a straight line from the current location (x=0, y=0) to the supplied coordinates, in this case x=10,y=20 Q Takes one pair of coordinates for a control point, one pair of coordinates as an end point. e.g[M,0,0,"Q",40,40,10,20] Draws a quadratic Bezier curve from the current location (x=0, y=0) to the second pair coordinates, in this case x=10,y=20, using the control point x=40,y=40 to shape the curve C Takes two pairs of coordinates for control points, one pair of coordinates as an end point. e.g[M,0,0,"C",75,80,125,20,150,50] Draws a cubic Bezier curve from the current location (x=0, y=0) to the third pair coordinates, in this case x=150,y=50, using two control points x=72,y=80 & x=125,y=20 to shape the curve Note that the SVG arc element (A) is not currently supported. More elements and variations on the elements are available, however, these are the ones you will use most of all. Using these we can build up something a little more extreme like this. Notice have I've used a cubic Bezier curve in the path to "hop" over the "Alpha" link: In this case the link path is made up of a mix of 8 elements defining various line segments and cubic Bezier curves, so although it looks complicated it's still composed of only the elements described above. Logically, the array reads like this: ["M", x, y, // Start point "L", x, y, // Straight line down for a bit "C", c1x, c1y, c2x, c2y, x, y, // Curve out towards Gamma "L", x, y, // Straight line horizontally towards the midpoint "C" , c1x, c1y, c2x, c2y, x, y, //The "hop" "L", x, y,  // Straight line horizontally away from the midpoint "C" , c1x, c1y, c2x, c2y, x, y, //return curve "L", x, y] // Straight line to the arrow endpoint A Final Note about Calculated Positions  You will note from the example above that some of the numbers are negative, and indeed, if you have been following through with the example, and debugging to examine the actual values, you'll have noticed that many of the positions end up with negative values.  Don't worry about this!  Everything, as they say, is relative, and the diagram layout will resolve itself correctly.  You can imagine that after you have positioned everything relative to an arbitary 0,0 origin, the diagram layout will re-base itself anyway and handle that. In the Next Article Now that we've completed coverage of the basics of layouts we spend some time in the next article exploring how you can incorporate flexibility into your diagram layout through configuration.

In the last article in this series I covered the basics of link routing and showed how the setPoints() API for a link could be used to create a non-straight line path between two nodes, as shown here: I...

A Guide to Diagram – Part 5 – Starting with Custom Layouts, continued

At the end of the last article we had achieved the following layout: Which was created by the following layout function: var LearningDiagramLayouts = { simpleVertical : function(layoutContext){  var nodeGap = 50;    var nodeCount = layoutContext.getNodeCount();    var linkCount = layoutContext.getLinkCount();    var xPos = 0;    var yPos = 0;            for (var i = 0;i<nodeCount;i++) {    var node = layoutContext.getNodeByIndex(i);      node.setPosition(new DvtDiagramPoint(xPos, yPos));      node.setLabelPosition(new DvtDiagramPoint((xPos + nodeGap) , yPos));      yPos += nodeGap;    }            var nodeSize = 20;    var startY = nodeSize;    var startX = nodeSize/2;    var endY = nodeGap;    var endX = startX;            for (var j = 0;j<linkCount;j++) {    var link = layoutContext.getLinkByIndex(j);      link.setPoints([startX, startY, endX, endY]);      link.setLabelPosition(new DvtDiagramPoint((startX - nodeGap) , (startY + 20)));      startY += nodeGap;      endY +=nodeGap;    }  }} To critique this layout as it stands, the obvious issue is that the Gamma link does not terminate in the correct place, but there is also a lot of hardcoding and calculations based on assumptions of fixed node sizes.  So the question is, how can we address these issues? Getting Sizing Information First of all we want to remove the hardcoding and make the layout more re-usable by making it sensitive to the sizing of the nodes that are passed to it.  There are three APIs that provide sizing information: getBounds() – returns a DvtRectangle object which defines the x,y position and the width and height of the node.  This rectangle will include the space allocated to overlay markers (recall that you can position markers outside of the logical node boundaries) getContentBounds() – returns sizing information for the node itself without accounting for the overlay markers getLabelBounds() – returns the sizing information for the node (or link) label. So you can rework the JavaScript to use some of these APIs: var LearningDiagramLayouts = { simpleVertical : function (layoutContext) {  var largestNodeBounds = LearningDiagramLayouts.getMaxNodeBounds(layoutContext);    var nodeGap = (2 * largestNodeBounds.h);    var nodeCount = layoutContext.getNodeCount();    var linkCount = layoutContext.getLinkCount();    var xPos = 0;    var yPos = 0;    var labelXPos = largestNodeBounds.w + 20;    for (var i = 0;i < nodeCount;i++) {    var node = layoutContext.getNodeByIndex(i);      var nodeHeight = node.getContentBounds().h;      node.setPosition(new DvtDiagramPoint(xPos, yPos));      var labelHeight = node.getLabelBounds().h;      var labelYPos = yPos + ((nodeHeight - labelHeight)/2);      node.setLabelPosition(new DvtDiagramPoint(labelXPos, labelYPos));      yPos += (nodeHeight + nodeGap);    }    ... You'll see here that first of all we work out the nodeGap variable by calling a utility function called getMaxNodeBounds() (shown below) which finds the largest node in the set. Using that information, the nodeGap variable is set to twice the height of this largest node, rather than it's old hardcoded size of 50. Then for each node we use the height of that node added to the gap to calculate the vertical position of the next node in the series. This will ensure that the layout will continue to work, even if nodes have differing sizes. In the updated version of the code we also take into account the height  and width of the node and the height of the label so that the label position is vertically centered on the center of the node and left aligned at a constant distance from the right hand side of the nodes.  This does not show very clearly with the current diagram, however, with larger and mixed sized nodes it becomes more obvious.  So your calculations should always take the actual metrics for the label itself into account. The getMaxNodeBounds Utility Function The  LearningDiagramLayouts.getMaxNodeBounds() utility function runs through the array of nodes and pulls out the largest dimensions for you.   getMaxNodeBounds : function (layoutContext) {    var nodeCount = layoutContext.getNodeCount();    var maxW = 0;    var maxH = 0;    for (var i = 0;i < nodeCount;i++) {    var node = layoutContext.getNodeByIndex(i);      var bounds = node.getContentBounds();      maxW = Math.max(bounds.w, maxW);      maxH = Math.max(bounds.h, maxH);    }  return new DvtDiagramRectangle(0, 0, maxW, maxH);  } So with this change to the node and node layout code here's how far we've got: So not really a huge amount of obvious progress over our starting point, but at least the code is now more generic than it was before. Let's sort out those links - they actually look worse! Correcting the Links So far, when accessing nodes and links you've done it using index based lookup, basically looping through the arrays provided by the LayoutContext.  However, link and node objects each have individual IDs and the LayoutContext provides associated getNodeById() and getLinkById() APIs to access a specific instance.  This is really important when dealing with links, as each link itself has APIs getStartId() and getEndId() to return the IDs of the nodes that the link joins together. So to correct all the links, rather than trying to keep a running total of the y position, as you did for the nodes, instead you can use the nodes associated with the link itself to work out the start and end positions.  In terms of logic, the idea is that the link will leave the start node in the middle of its bottom edge and join the end node in the middle of its top edge. Here's the amended version of the code for the links loop:    ...   var linkGap = 4;   for (var j = 0;j < linkCount;j++) {      var link = layoutContext.getLinkByIndex(j);      var startNode = layoutContext.getNodeById(link.getStartId());      var endNode = layoutContext.getNodeById(link.getEndId());      var linkStartPos = LearningDiagramLayouts.getNodeEdgeMidPoint(startNode,"s");      var linkEndPos = LearningDiagramLayouts.getNodeEdgeMidPoint(endNode,"n");          link.setPoints([linkStartPos.x, (linkStartPos.y + linkGap),                      linkEndPos.x, (linkEndPos.y - linkGap)]);      var labelXPos = linkStartPos.x - (link.getLabelBounds().w + 20);      var labelYPos = linkStartPos.y +                       ((linkEndPos.y - linkStartPos.y - link.getLabelBounds().h)/2);      link.setLabelPosition(new DvtDiagramPoint(labelXPos, labelYPos));   }   ... You can find the complete JavaScript file, including the LearningDiagramLayouts.getNodeEdgeMidPoint() utility function, linked at the end of this article The result of that change shows the links now anchored in the correct place and each of the labels now centered and right aligned to the relevant link. You'll notice in the calculations above that we make increasing use of the available metrics to work out the position of objects.  For example, when positioning a link label halfway along the length of the link, we again take the actual height of the label into account in the calculation, not just the length of the link.  This ensures that the result will look right, no matter what the label font size.  There's just one problem left to sort out in this basic layout.  The algorithm is a little too literal, and the "Gamma" link, although correctly joining "Third Node" and "First Node", is taking the most direct route to do so and is overlapping the other links. So you need to add a little logic to re-route it. Introducing Link Paths So far we've been using links in a very simple mode, just a straight line joining two points in space.  However, links can follow complex paths, and indeed, part of your challenge when creating your own diagrams will be in calculating these paths though a busy nodescape to avoid overlaps.  There is no magic formula here to fit all occasions; it all comes down to math.  In this case we want to route the "Gamma" link out to the left and back around to the "First Node" so we will have to define a path with 5 segments (assuming that the start and end points stick to our standard approach for the other links in the diagram). It's worth mentioning at this point that links can, of course, be made up of straight lines with right angle junctions. But you can also get creative and use features such as curving lines and rounded junctions.  This is a topic for another day, for now we'll stick to orthogonal routing. So what you have to do here is to calculate a series of points and call the same setPoints() API on the link to draw it:  if (linkEndPos.y > linkStartPos.y) {  //A normal link    link.setPoints([linkStartPos.x, (linkStartPos.y + linkGap),         linkEndPos.x, (linkEndPos.y - linkGap)]); } else {    // The case where we need to re-route     // Segment 1 - keep heading down for a short distance     var turn1 = new DvtDiagramPoint();    turn1.x = linkStartPos.x;    turn1.y = linkStartPos.y + (largestNodeBounds.h/2);    // Segment 2 - head left far enough to avoid overlap with the other link labels    var turn2 = new DvtDiagramPoint();    turn2.x = turn1.x - (largestLinkLabelBounds.w + 40);    turn2.y = turn1.y;    // Segment 3 - Back up the diagram to a point equally above the end node    var turn3 = new DvtDiagramPoint();    turn3.x = turn2.x;    turn3.y = linkEndPos.y - (largestNodeBounds.h/2);    // Segment 4 - Back to the center line    var turn4 = new DvtDiagramPoint();    turn4.x = linkEndPos.x;    turn4.y = turn3.y;    // Segment 5 - And down to the end node for which     // we already have the coordinates    //Now pass in the path:    link.setPoints([linkStartPos.x, (linkStartPos.y + linkGap),                    turn1.x, turn1.y,                   turn2.x, turn2.y,                   turn3.x, turn3.y,                   turn4.x, turn4.y,                   linkEndPos.x, (linkEndPos.y - linkGap)]);  } And here's the final result, to create this I did a little work to ensure that the label for the re-routed link was also in the corrected position: The Full JavaScript Source There is quite a lot of JavaScript now so I've linked the end result of this layout's evolution here. In the Next Article In the last two articles I've covered the basics of layouts, the positioning of nodes and the routing of links. You should be aware that there are multiple approaches that you can take here and not all layouts will consist of one loop through the nodes and one loop through the links.  Sophisticated or busy layouts may need multiple iterations through the population of nodes and links to calculate all of the relative positioning.  Next time, I'll briefly explore some of the more interesting ways of defining links, introducing label rotation and curves.

At the end of the last article we had achieved the following layout: Which was created by the following layout function: var LearningDiagramLayouts = { simpleVertical : function(layoutContext){ var...

A Guide to Diagram – Part 4 – Starting with Custom Layouts

As I discussed at the beginning of this series, there was no way that, out of the box, diagram would be able to achieve every possible layout that might be demanded of it. Therefore, the whole process of defining the layout is opened up for you to plug your own implementation in.  In the next four articles in this series I'll be exploring this topic, starting with the basics in the first two, and then building up the complexity as we go along. As well as following along through the coding in these articles, you can also check out the layout example in the diagram on-line demos.  This provides some alternative examples that will add to your overall knowledge  Getting Started  If you look back to Part 2 of this series, recall that we plugged in an example layout using a <dvt:clientLayout> tag nested within the <dvt:diagram>. As a point of fact, you can actually define multiple layouts within a single diagram, something we'll discuss in a later article on containers, so you may have more than one clientLayout tag, but for now let's stick to just one.  The <dvt:clientLayout> tag has three attributes: name – an identifier that you use for the layout.  This value is then referenced from the layout property of the diagram tag and which of course tells the diagram which layout to use. method – identifies the name of a JavaScript function that will perform the layout.  We'll look at that function in detail later on in the article. featureName – lets the framework identify exactly which JavaScript source files are required to locate and run the function identified in the method attribute. Defining a Feature Within the ADF Faces runtime environment, a feature is a named related group of JavaScript files used by the framework.  You may have come across features whilst tuning your ADF applications, using it to  define exactly which sets of JavaScript files are initially downloaded to the browser and which are only downloaded on demand.  If you're not familiar with the concept don't worry, I'll cover everything that you need here.  So the first step to defining your feature is the creation of an adf-js-features.xml file.  This file needs to be put in your ViewController/src/META-INF directory. That directory should already exist and contain an adf-settings.xml file. So create a new XML file with the correct name in this location and define the contents like this: <?xml version="1.0" encoding="utf-8"?><features xmlns="http://xmlns.oracle.com/adf/faces/feature">   <feature>  <feature-name>LearningDiagramLayouts</feature-name>    <feature-class>js/layouts/learningDiagram.js</feature-class>  </feature></features> You can see that what we have done here is define a feature name and associate that name with a particular JavaScript file on the server side classpath.  If required, you can define multiple <feature-name> entries to add several JavaScript files, and you can also reference other features using the <feature-dependency> element.  In this case though, we just have the one JavaScript file to worry about.  Defining the JavaScript  The location defined in the adf-js-features file has to point to a location on the Java classpath, so you need to create your JavaScript file under the projects /scr directory.  In this example ViewController/src/js/layouts. If you create a js file from the new gallery into this location, it will pop up a warning: Just select Yes to proceed. At runtime, the framework will ensure that your JavaScript file makes it to the browser. Recall from the <dvt:clientLayout> component, that we need to have defined a method name which will be the actual function that will be called by diagram to handle the layout. So within the new learningDiagram.js file create a starter function thus: /* Sample layout used for the diagram series of blog articles */var LearningDiagramLayouts = { simpleVertical : function(layoutContext){  alert("Hello from your layout code ");  }}   Here I can defined a function with the name of LearningDiagramLayouts.simpleVertical  You'll notice two things: It does not actually do anything yet – just pops up an alert. Don't worry though, once we have everything wired up we'll do something more constructive here.  The function is accepting an argument called layoutContext.  This is a key object that will provide the function with all of the information that it needs about the nodes and links that it needs to lay out. Wiring the Diagram to the layout Now that we have a custom layout of our own defined we can alter the diagram configuration to use it: <dvt:diagram id="d1" summary="Example Diagram" layout="learningVertical"> <dvt:clientLayout name="learningVertical" method="LearningDiagramLayouts.simpleVertical"                    featureName="LearningDiagramLayouts"/>   ... So here, I have defined a arbitrary name of learningVertical to point to the LearningDiagramLayouts.simpleVertical() function in the JavaScript file pointed to by the LearningDiagramLayouts feature definition. Configuring Your Development Environment If you just run the page as it stands you'll probably see a stack trace in the console complaining about a missing resource error.  The framework will not be able to find the .js file you've defined. Why?  Well we've put it in the /src directory and that location is not on the classpath at runtime.  We could just put the .js files under the /classes output directory, but then it would be blown away every time you carry out a clean of the project, not a great idea! Fortunately, we can leave the file safely under the /src directory but tell JDeveloper to copy it across to the /classes directory with every compile. To do this, double click the project in the Application Navigator to bring up the project properties. Select the Compiler node and update the list of file types shown in the "Copy File Types to Output Directory" field to include .js files (use semi-colon as a delimiter) Now, whenever, you make a change to the JavaScript, just remember to hit the compile key, or button on the toolbar, to cause the file to be copied across to the /classes directory.   A Note About your Runtime  and Debugging Environment  When we are creating layouts, it's all JavaScript code, so you'll probably end up debugging using a tool such as Chrome Developer Tools or FireBug.  These tools make JavaScript debugging really simple, so it's well worth spending a bit of time learning to use them, rather than falling back to using alert() statements. One thing to be cognizant of is the fact that browsers really love to cache your JavaScript, so if it seems like you're seeing an old version of the code then it's time to clear your browser cache.  Tools like Chrome Developer Tools have special modes that you can switch on to prevent caching all together, so it's a great idea to take advantage of that and save yourself from much head scratching.   Defining a Basic Layout  At the moment the layout function LearningDiagramLayouts.simpleVertical() actually does no layout, it just pops up an alert and all the nodes remain huddled in the center of the screen. So let's start to build this simple layout. By the end of the first example, if you follow along, you'll end up with a layout that distribute the nodes vertically like this: Initially, I'll  start off by hardcoding distances and sizes but as we go along the code will evolve and become more dynamic. Positioning Your Nodes The basic process of laying out a diagram is to loop though an array of nodes and an array of links and set positioning information on each of them. So let's start off with nodes.  The layout context object that is passed to the layout function contains the information about the number of nodes, using the getNodeCount() API, and provides access to each node object using the getNodeByIndex() API. Using these, you can loop through the nodes to access each in turn. Once you have a node, you can call its setPosition() API to locate it on the diagram space. The position is passed in the form of a DvtDiagramPoint() object which defines the simple x and y coordinates.  It's worth noting at this point that we're working in relative units here, not absolute.  So if you set a node at point 200,200 in the diagram this does not imply a point at exactly at 200px / 200px relative to the top left hand corner of the diagram component.  The actual position will depend on the zoom level that the diagram is currently operating at, and the setting of the viewport on the diagram.  These are both topics which we'll cover in later articles, so for now just remember that you are just working in relative units.  So, with the three APIs you've seen so far (getNodeCount, getNodeByIndex and setPosition) you have enough knowledge to do something.  Here's your very first layout: var LearningDiagramLayouts = { simpleVertical : function(layoutContext){  var nodeGap = 50;    var nodeCount = layoutContext.getNodeCount();    var xPos = 0;    var yPos = 0;    for (var i = 0;i<nodeCount;i++) {    var node = layoutContext.getNodeByIndex(i);      node.setPosition(new DvtDiagramPoint(xPos, yPos));      yPos += nodeGap;    }  }} So in this case the nodes are all at position 0 on the x axis and then incrementally 50 apart vertically. Here's what it looks like: So some progress. The nodes are distributed vertically; however, there's no sign of the link,s and the labels are overlapping the nodes themselves.  As we're dealing with just the nodes at the moment, let's concentrate on sorting out those labels before we move on. Positioning the labels is just like positioning the nodes themselves.  There is a get/setLabelPosition() API on the node which takes a DvtDiagramPoint to define the new location for the label.  So by adding a single line, you can offset the labels to the right of their nodes using the same fixed gap size: node.setLabelPosition(new DvtDiagramPoint((xPos + nodeGap) , yPos)); And that sorts the label out nicely, although we still have a bit of a mess behind the first node that represents all of the links and link labels. Positioning Your Links No surprises here, the process for laying out links is pretty similar to that of nodes.  You can obtain a count of the number of links from the LayoutContext object using the getLinkCount() API and then loop through them using getLinkByIndex() .  Labels are handled in exactly the same way as for the node, so you'll see the code there is very similar, although in this case I'm offsetting the label to the left, approximately midway along the link When positioning an actual link, however, you have two coordinates to worry about; a position for the start and the position for the end. This is done through the setPoints() API on the link object which takes an array of x,y coordinates rather than just a single pair. So, here's the next part of the code where you loop through the links as well and set the positions of the links and link labels:    ...   var nodeSize = 20;   var startY = nodeSize;   var startX = nodeSize/2;   var endY = nodeGap;   var endX = startX;   for (var j = 0;j<linkCount;j++) {      var link = layoutContext.getLinkByIndex(j);      link.setPoints([startX, startY, endX, endY]);      link.setLabelPosition(new DvtDiagramPoint((startX - nodeGap) , (startY + 20)));      startY += nodeGap;      endY +=nodeGap;   }   ... And that combined with the nodes loop results in: So we've made some considerable progress, but there are certainly some issues still, not least that the link "Gamma" leaves from "Third Node" but never arrives at it's destination of "First Node". However, it's a start! In the Next Article Now we have the basics of how the layout function works we'll start to look at finishing off this basic layout and in the process remove all the hardcoded sizes from the mix.

As I discussed at the beginning of this series, there was no way that, out of the box, diagram would be able to achieve every possible layout that might be demanded of it. Therefore, the whole process...

A Guide to Diagram – Part 3 – Styling your Links

In the last article we looked at nodes and what you could put in them, so to round off the basic story we need to follow that up with links.  There's not really too much to configure when it comes to links, if you have a look at the tag doc for the <dvt:diagramLink> you'll see pretty much what you would expect in terms of the ability to set the color, thickness and style of the links through attributes. So we could, for example, enhance the sample diagram that I've been using for these articles with something a little more interesting.  In this case I've extended the data-model for the links to create two extra attributes; weight and status. Then we can amend the <dvt:diagramLinks> section of the diagram definition with multiple types of links based on the combination of the new status and weight attributes: <dvt:diagramLinks id="dls1" value="#{diagramModel.links}" var="link"> <dvt:diagramLink id="dl1" rendered="#{link.status eq 'COMMITTED'}"                    startNode="#{link.sourceNodeId}"                   endNode="#{link.destinationNodeId}"                   linkWidth="#{link.weight}" linkStyle="dash"/>  <dvt:diagramLink id="dl2" rendered="#{link.status eq 'PLANNED'}"                    startNode="#{link.sourceNodeId}"                   endNode="#{link.destinationNodeId}"                    linkWidth="#{link.weight}" linkStyle="dot"/>  <dvt:diagramLink id="dl3" rendered="#{link.status eq 'COMPLETE'}"  startNode="#{link.sourceNodeId}"                   endNode="#{link.destinationNodeId}"                    linkWidth="#{link.weight}" linkStyle="solid"/>                 </dvt:diagramLinks> Here's the result: Connectors The final look and feel control over the link is of course the startConnectorType and endConnectorType.  Out of the box you have the following options: arrow arrowConcave arrowOpen circle rectangle rectangleRounded So we can apply some of those to the link definition in the sample diagram e.g. ... <dvt:diagramLink id="dl1"                 rendered="#{link.status eq 'COMMITTED'}"                  label="#{link.label}"                 startNode="#{link.sourceNodeId}"                 endNode="#{link.destinationNodeId}"                 linkWidth="#{link.weight}" linkStyle="dash"                 startConnectorType="circle"                 endConnectorType="arrowOpen"/> ... With the following result: You'll notice that there is a bit of a collision going on between the label and the connectors of the Third Node, just because the label happens to be on the bottom of the node where the two links are anchored. Don't worry though, when we come on to discuss custom layouts in a later article we'll cover how you can control the termination point of the links to avoid this.  Link Facets Diagram links, just like nodes, support some facets to add a little more flexibility. Label Facet Not surprisingly, links can be labeled and the label can either be applied using the link label attribute on the diagramLink component, or using the label facet.   In this case I've added an additional getLabel() property to the SampleLink class and I'm displaying it using the label attribute of the diagramLink component.  The label facet of the link is not as generous as that of the diagram node, so you can't use it to define complex layouts for the link label.  You are only allowed to use a either a single <af:outputText> or <dvt:marker> as the child of this facet, no layouts or other fancy stuff.  The use of a marker, however, will provide you with the capability to add an image onto the link (it will overlay the link line).  Note that just like the background facet on the <dvt:diagramNode> the marker image in this case is passive and any action associated with the marker will be ignored.  In a later article, I'll look at the selection and eventing model of diagram and we'll see how actions can be carried out when a link is selected. You'll notice that you don't have any obvious control over the position of the label, relative to the link. In the example above, it's just overlaid on the midpoint of the link.  Agaiin, when we look at diagram layouts, I'll show how you can control this.  StartConnector / endConnector Facet As shown, there are a number of pre-built connectors built into the link component, however, if you have the need for something different, you can use these two facets to provide your own link terminators to augment the standard shapes.  Not surprisingly, the component to nest here would be a <dvt:marker> pointing to the image that you want to use.  Again an SVG image should be used for preference, just to ensure clean scaling as the connector will be scaled to match the line width - something you can see with the three different line widths in our sample.  Just like the label facet, markers used here will be passive and purely decorative. In the Next Article  That's it for links, a pretty short topic. We still have a lot of good stuff to talk about in relation to the diagram event model, grouping and stacking.  However, to really progress much further, we need to start looking at layouts and how to create your own, so that will be the subject of the next set of articles in this series.

In the last article we looked at nodes and what you could put in them, so to round off the basic story we need to follow that up with links.  There's not really too much to configure when it comes...

A Guide to Diagram – Part 2 – Content for Nodes

In the last article I demonstrated how we could create a simple data model with three nodes and some links between them.  However, the end result was less than impressive from a visual perspective: In this article I'll explore what you can actually do to the nodes to create something that is visually more attractive, and which conveys a little more information. The idea of course is to add further ADF components inside of the diagramNodes to include more information and maybe images as well.  However, you can't use every ADF component inside a node, there is a restricted subset of components that you can use (See the <dvt:diagramNode> tagdoc).  Importantly, don't expect to use any input components on the nodes.  If you need to "edit" the content of a node then you'll have to use popups launched from the node in question to do so. The Basic Components The following components are officially supported within a node: af:button / commandButton / goButton af:image af:link / commandLink / commandImageLink / goLink af:outputText / outputFormatted dvt:marker / pointLocation  And the following layout components: af:panelFormLayout af:panelGroupLayout af:panelLabelAndMessage af:spacer af:separator f:facet dvt:panelCard / af:showDetailItem And behaviors: dvt:drillBehavior dvt:isolateBehavior dvt:restoreBehavior dvt:rowDisclosureBehavior af:showPopupBehavior Of course any popup referenced by showPopupBehavior references content outside of the diagram and so any popups can contain the full range of ADF and DVT components. What you need to be aware of  When ADF components are rendered inside of a diagram node they are not output to the browser in the normal way.  Instead, they are transformed into the corresponding SVG elements within the diagram.  One result of this transformation is that any style classes applied to the component using the styleClass attribute will be ignored.  However, all is not lost! The framework will support a subset of CSS style directives directly defined in the inlineStyle attribute for the component. The CSS that is supported in this way includes background and border styling and font information.  You should be aware, however, that any style directive that involves sizing is not going to be respected in absolute terms as the nodes on the diagram will be scaled depending on the zoom level.  You'll also note that there is no support for <af:clientListener> and <af:clientAttribute> within a node.  When components are rendered on a diagram node they do not currently support any client side manipulation and do not expose a client API to JavaScript in the browser.  As well as the standard layouts and output components that you will be more than familiar with, diagram can also use some extra components that may be less familiar; panelCard and marker. PanelCards PanelCards (<dvt:panelCard>) were first introduced with the Hierarchy Viewer component, and provide a way of defining a series of "cards", defined by af:showDetailItem tags, which are arranged in a logical ring inside of the panel.  The user is able to move from card to card using the navigation breadcrumbs or button as shown:   In the above example there are two <af:showDetail> components, the first displaying phone number and email, and the second the address. You can define an animation used for the transition between cards using the effect attribute which supports various sliding and rotating animations: immediate - no transition effect slide_horz - old content slides out on one side while new content slides in from the other side flip_horz - the showDetailItem flips over to reveal new contents node_flip_horz - the whole node flips over to reveal new contents  Markers  Another supported child of the diagramNode that you may not be familiar with already is the marker.  Markers are already used with other DVT components such as maps, and specifically in cases where a scaling shape component is needed.  There are several pre-defined shapes for marker: Circle Square Rounded rectangle Diamond Plus sign Upwards facing triangle Downwards facing triangle Human figure The look of these standard shapes can be controlled in terms of sizing of course, plus fill and line colors, gradients, opacity and rotation. So they make for very flexible "primitives" to represent either entire nodes or node overlays (as we'll see shortly).  However, as well as the built-in shapes you can provide your own marker shapes in the form of images provided as .png, .jpeg etc. or for clean scaling during zoom, as SVG images.  Markers can themselves also have a label attribute, if required, so often it's sufficient to use a marker as the sole content of your diagram node. Here's an improved version of my simple diagram, from part 2 in this series, where I've updated the bare <dvt:diagramNode> definition to now use a marker to represent the node: ...<dvt:diagramNode id="dn1" nodeId="#{node.uniqueNodeId}" label="#{node.nodeLabel}"> <f:facet name="zoom100">  <dvt:marker shape="circle"  height="20" width="20" fillColor="#ff0000" borderColor="#000000" borderStyle="solid" borderWidth="1.0"/> </f:facet></dvt:diagramNode>... And here's the visual result of that simple change   I think that you can see that the diagram is instantly more useful! Node Facets Like many other JSF components, the diagramNode supports a variety of facets, you can divide these up into three groups; general facets, zoom facets and container facets.  For now I'll ignore the container facets, I'll look at those in a later article when I cover containers and grouping, but you'll encounter the first two categories early on.  Zoom Facets The concept of zoom facets may be familiar to you if you've used hierarchy viewer in the past. The point here is that although diagram can successfully scale content as the user zooms in and out, there is a point where the information present on a node is unreadable because it becomes too small.  Zoom facets give you four content buckets (zoom100, zoom75, zoom50, zoom25) in which you can include different sets of components.  Thus at the zoom100 level you might define a complex layout using a panelcard and images and generally pack in all the contact information for an employee.  However on the zoom25 facet you might just include the picture of the employee, therefore using the available space to it's best advantage when the node area is tiny.  As the user zooms in an out each of these zoom facts will be selected appropriately to best fit the contents of the node automatically.  You will always have a zoom100 facet defined, however, the others are optional.  General Facets The Label Facet The label facet provides you with an opportunity to define specific styling for the node label.  As such, it replaces (and overrides) the label attribute of the <dvt:diagramNode> itself. Generally you'd use this facet to alter the styling of the label, but you can also use it to achieve useful things such as creating a multi-line label,. You would do this  by including a vertical panelGroupLayout within the label facet and creating each line of the label with a separate <af:outputText>. You can even include other components such as images, links and buttons in this facet should you desire. The Background Facet As the name suggests the background of the node can be set with the content of this facet. As such <af:image> and <dvt:marker> tags can be used here to provide an image.  The actual content of the Zoom facets will be overlaid on top of this background.  The contents of this facet will be zoomed with the node as the user manipulates the diagram, therefore for optimum quality it's best to use <dvt:marker> with an SVG image as the source here. Here's an example where I'm using an SVG in the background facet and normal text in the zoom100 facet, plus a label (PDB1) on the <dvt:diagramNode> itself: Note that a <dvt:marker> tag used as a background is purely visual and any action or actionListener defined on it will be ignored.  The image that you supply in the background facet will be automatically be sized to fit the actual contents of the nodes, so choose images here that are well matched to the contents of the node or unwanted things may happen.  For example, if I'm careless and don't round my free space percentage in my outputText in this diagram node -  this would happen - so be careful:  Here's the code for this node as a reference: <dvt:diagramNode id="dn1" nodeId="#{node.uniqueNodeId}" label="#{node.dbName"> <f:facet name="zoom100">  <af:panelGroupLayout layout="vertical" halign="center"                         inlineStyle="height:40px;margin-top:20px;margin-left:5px;margin-right:5px;">    <af:outputText value="Free Space"/>      <af:outputText value="#{node.freeSpace}"/>    </af:panelGroupLayout>  </f:facet>  <f:facet name="background">   <dvt:marker source="/images/database.svg"/> </f:facet></dvt:diagramNode>  The reality is that you will not use the background facet that much, using the Zoom facets is better to achieve the same end, until you start to use containers and node grouping.  Then background becomes useful, as we shall see in a later article. The Overlay Facet The overlay facet is an extremely useful feature.  It expects one or more <dvt:marker> tags as children, and these markers, as the facet name suggests, overlaid on top of the node contents.  Here's an example of the previous example (correctly sized!) with an overlay indicating that the 12c pluggable database represented by the node is up.  Here's the overlay facet definition that created that: <f:facet name="overlay"> <af:group>    <dvt:pointLocation pointX="100%" pointY="0%">      <dvt:marker shape="triangleUp" fillColor="#00ff00" borderColor="#00a500" borderStyle="solid" height="16" width="16"/>    </dvt:pointLocation>  </af:group></f:facet> You'll notice here that a new tag has been introduced - <dvt:pointLocation>.  This tag allows us to position the marker either in absolute, or more normally, in percentage terms, relative to the top left corner of the node (at 0,0). Note that you can specify percentage values that are greater than 100% or that are negative. This will to allow you to offset the markers as required left, right, up and down, from the body of the node.  The overlay facet can also support multiple markers within the overlay group, so by adding different pointLocations we can apply "badges" to different parts of the node, like this: <f:facet name="overlay">  <af:group>    <dvt:pointLocation pointX="100%" pointY="0%">      <dvt:marker shape="triangleUp" fillColor="#00ff00" borderColor="#00a500" borderStyle="solid"                   height="16" width="16"/>    </dvt:pointLocation>    <dvt:pointLocation pointX="100%" pointY="90%">      <dvt:marker source="/images/info.svg"                   height="16" width="16"/>  </dvt:pointLocation> </af:group></f:facet>  As well as being visual indicators, the markers can also add functionality, specifically you can define action, actionListener and destination(url) properties to use it to invoke navigation or code execution.  Additionally you can define a <af:showPopupBehavior> tag as a child of the marker to invoke a popup when the marker is clicked. The final consideration with all of these general facets (label, background and overlay) is that they are present no matter what the zoom level, they do not support  different definitions at the 100, 75, 50 and 25% levels. But What if I Have Different Types of Node? Within a diagram node you can do all of the usual tricks with expression language to display different values, use different images and even switch components on and off with the rendered property.  However, if you have several distinct types of nodes you may actually want to define separate <dvt:diagramNode> components within the diagram tag. This will help to keep your code easier to read and is very common with more complex diagrams where you may need to define different properties to different classes of nodes. You can control which diagramNode definition is used to display a particular member of the nodes collection using the rendered property on  the <dvt:diagramNode> component itself.  For example, if you look at the Simple Rules Editor demo for diagram you will see multiple node definitions, each of which uses an expression like this to control which definition handles which node definition: rendered="#{node.ruleNodeType eq 'CONDITION'}" So in this case, this node defintion will be used when the node type evaluates to the String value "CONDITION". Guidelines for Node Design Diagrams are a very effective way of conveying many types of data, but they excel at being able to help users visualize a large number of complex connections within large data sets.  Diagram has been designed to scale to handle these large datasets and is more than capable of displaying of hundreds of nodes and links. However, when designing your diagram you want to keep several factors in mind, to optimize the user experience and responsiveness: Keep the contents of your nodes simple.  Rather that overloading your diagram with large amounts of text, you may find that simple images may be much easier for the user to understand when trying to take in the entirety of the diagram.  You can then use drilldown to provide access to more detailed information if it is required. Use the zoom facets.  If you are including detailed content in each node then be sure to define relevant levels of detail at each zoom level so the content of the nodes remains readable and usable. If using an image to represent a node then seriously consider using an SVG image format. SVG images will scale much more gracefully as the user zooms in and out.  Don't display all of the data at once.  Features such as containership which we'll cover in a later article can help to hide some of the complexity of the diagram, allowing the user to drill down into more detail as required.   You can also investigate using an intermediate or wrapper model that filters the full data model, limiting the number of nodes that need to be displayed at any one time.  In the Next Article  Now that we understand a little about formatting nodes and their contents, the next article will complete the picture and talk about links. 

In the last article I demonstrated how we could create a simple data model with three nodes and some links between them.  However, the end result was less than impressive from a visual perspective: In...

A Guide to Diagram – Part 1 – Data for Nodes and Links

I guess the first thing to get your head around with diagram is the core data structures that are required. Fortunately this is not a very complex area although it does differ in one small respect from that for other components that you might be worth dealing with. Fundamentally the diagram represents two sets of separate, but related, data objects.  A set of nodes, and a set of links that join those nodes. The important thing here is that these are supplied as two separate collections of data rather than say a single recursive hierarchy.  So in order to build a diagram you will need a collection of node objects and a collection of link objects.  Note that when I say "collection" here I mean that these sets of objects can be provided either in the form of something that implements the List interface (e.g. java.util.ArrayList) or a CollectionModel (org.apache.myfaces.trinidad.model.CollectionModel). The latter of these two categories includes data provided by the ADF binding layer in the form of a table or hierarchical binding (the same type of binding that you would use for an ADF table), so mapping data in from your model layer should be a snap.  So what's a Node?  A node collection can be a collection of anything, diagram does not impose any particular data structure or naming on you. All you need is an attribute (exposed through a public getter) that can act as the unique ID for the node.  This attribute can be of any type although generally you'll want to keep it to something simple such as a String, int, or long for example.  What does matter, is that each row in the collection needs to have a unique one.  If you use an object type of your own for this node ID be sure to implement the equals() method of that object. You map the collection of nodes through a <dvt:diagramNodes> tag using the value attribute as the way to pass it in. The diagramNodes tag acts like many other iterating components used in ADF Faces. It has a second attribute called var that we use as the way to reference each row from the value collection as we stamp it out.  By convention var is usually set to "node".  As each node is stamped out, we use a <dvt:diagramNode> component to represent it.  I'll talk more about what can actually be represented within a node in the next article.  A Basic Example Just to give you a chance to try this out yourself, here is a super simple example that we'll build up as we go along.  To start off with, here's a really basic definition for a node object : public class SampleNode { private int _uniqueNodeId;  private String _nodeLabel;  public SampleNode(int id, String label){  _uniqueNodeId = id;    _nodeLabel = label;  }  public int getUniqueNodeId() {   return _uniqueNodeId;  }  public String getNodeLabel() {  return _nodeLabel;  }} And then let's create a collection of those in a managed bean so that we can access it from diagram: /** Mapped as a managed Bean called "diagramModel" * SessionScoped */public class DiagramDataModel { private List<SampleNode> _nodes;  public DiagramDataModel(){ //Seed the diagram with three nodes   _nodes = new ArrayList<SampleNode>(3);    _nodes.add(new SampleNode(0,"First Node"));    _nodes.add(new SampleNode(1,"Second Node"));    _nodes.add(new SampleNode(2,"Third Node"));  }  public List<SampleNode> getNodes() { return _nodes;  }} And map that into the UI <dvt:diagram id="d1" summary="Example Diagram"> <dvt:diagramNodes id="dns1" value="#{diagramModel.nodes}" var="node">  <dvt:diagramNode id="dn1" nodeId="#{node.uniqueNodeId}" label="#{node.nodeLabel}"/>  </dvt:diagramNodes></dvt:diagram> OK, now if you've followed along and run the page, something will happen although all you'll actually see is a mess of overlapping text in the top left hand corner of the diagram component. Not very useful yet, but stick with me here. On to Links So we have nodes, what about the links (or edges) that may join them together? As I mentioned these have to be supplied as a separate collection from the nodes. This allows for maximum flexibility as a node can be linked to as many other nodes as required, or to zero other nodes or even several times to the same partner node. Just like the data structure required for a node, the basic data structure for a link is very simple and flexible.  This time though, it needs two specific attributes; a source node and a destination node. As you may of guessed, these need to correspond to the unique node identifiers that we defined on our node objects and passed to the nodeId attribute of the diagramNode tag. Needless to say, any nodeId referenced by a link has to exist on the diagram otherwise the link will not display. The source and destination nodes are mapped using the startNode and endNode attributes respectively in the <dvt:diagramLink> tag. Our Basic Example Continued… So let's extend our working sample to add links. First of all define a Java type for an individual link: public class SampleLink { private int _sourceNodeId;  private int _destinationNodeId;  public SampleLink(int source, int destination){  _sourceNodeId = source;    _destinationNodeId = destination;  }  public int getSourceNodeId() {  return _sourceNodeId;  }  public int getDestinationNodeId() {  return _destinationNodeId;  }} Then we can amend the model class we created earliet to include some of these links as well to join the existing nodes: /** Mapped as a managed Bean called "diagramModel" * SessionScoped */public class DiagramDataModel {  private List<SampleNode> _nodes;  private List<SampleLink> _links;  public DiagramDataModel(){     //Seed the diagram with three nodes    _nodes = new ArrayList<SampleNode>(3);    _nodes.add(new SampleNode(0,"First Node"));    _nodes.add(new SampleNode(1,"Second Node"));    _nodes.add(new SampleNode(2,"Third Node"));    //And links to join each to the next    _links = new ArrayList<SampleLink>(3);    _links.add(new SampleLink(0,1));    _links.add(new SampleLink(1,2));    _links.add(new SampleLink(2,0));    }  public List<SampleNode> getNodes() { return _nodes;  }  public List<SampleLink> getLinks() {   return _links;  }} Just like the nodes, the links are expressed through a duet of tags:  <dvt:diagramLinks> which stamps out the collection of links using the standard value and var combo, and <dvt:diagramLink> which is responsible for stamping out each link instance: Just as in the case of the nodes, the actual amount of information actually required is minimal, just the source and destination unique node ids: <dvt:diagram id="d1" summary="Example Diagram"> <dvt:diagramNodes id="dns1" value="#{ diagramModel.nodes}" var="node">  <dvt:diagramNode id="dn1" nodeId="#{node.uniqueNodeId}" label="#{node.nodeLabel}"/>  </dvt:diagramNodes>  <dvt:diagramLinks id="dls1" value="#{diagramModel.links}" var="link">  <dvt:diagramLink id="dl1"                      startNode="#{link.sourceNodeId}"                     endNode="#{link.destinationNodeId}"/>  </dvt:diagramLinks></dvt:diagram> Now again, if you run, this you'll just get a mess of overlapping text in the top left corner of the diagram, so we need to make one small addition to help it all make sense – a layout. Don't worry about the mechanics of creating or using a layout at this stage I'll cover that in a lot of detail in a later article, instead just do the following: Download the ADF Faces demo .war file from the OTN ADF download page From within the .war file extract the dvt-demo-javascript.jar file (use your favorite zip tool to unpack the .war and look in the WEB-INF/lib directory for this file. Drop the jar into the public_htmlWEB-INF/lib directory of your project (you may have to create this)  Then amend the page slightly to reference one of the layouts.  In this case I'm using the circle layout: <dvt:diagram id="d1" summary="Example Diagram"  layout="circleLayout"> <dvt:clientLayout name="circleLayout" method="DemoCircleLayout.circleLayout" featureName="DemoCircleLayout"/> … The <dvt:clientLayout> tag is responsible for identifying exactly what JavaScript needs to be run to layout the node and it defines an alias (in this case circleLayout) that the diagram will refer to using the layout attribute.  As we will see in later articles when I explain layouts in more detail, an individual diagram may actually use multiple clientLayouts. Now when the page is run, here's the result.  It's still rather plain, however, a semblance of structure is beginning to emerge as the nodes are now distributed in a circle and joined with links, we're on the right track! In the Next Article Next time I'll be exploring what you can do with the node contents in a little more detail, which in turn, will help to transform our starter diagram into something a little more attractive.

I guess the first thing to get your head around with diagram is the core data structures that are required. Fortunately this is not a very complex area although it does differ in one small respect...

Welcome and Overview of Data Visualizations in ADF 12.1.3

Welcome to the Oracle Data Visualization blog! In this blog, you can expect to see articles on the latest features in Oracle Data Visualizations, tips and tricks for using the components, and more. Overview of Data Visualizations in ADF 12.1.3 The ADF Data Visualizations deliver responsive interactivity and animation across a broad set of industry leading HTML5 components, including: 30+ Chart types, including spark charts, dual-y, and stacked varieties Gauges: Dial, LED, Rating, and Status Meter Gantt Charts: Project, Resource Utilization and Scheduling Maps: Geographic and Thematic And Many Others: Diagram, Hierarchy Viewer, Pivot Table, Sunburst, Timeline and Treemap  In the latest release of JDeveloper (12.1.3), we have introduced a number of new features in Data Visualizations, which are discussed below. New DVT Client Side Charting Solution The New DVT Client Side Charting Solution provides the following benefits: Client Side Resizing: Ability to resize and fit to containers without the need to go back to the server for layout.   Improved Server Scalability: Layout is offloaded to the client, reducing server workload and increasing scalability of applications. Rich Set of Features: Over 30+ chart types Redesigned zoom and scroll Marquee zoom and selection Redesigned Time axis Hide and show series and ability to change layout with client side rescale Improved data labeling New Gauges are now focused on the stamping use cases and support input. Gauge types include: LED, status meter, dial, and the new rating gauge. Thematic Map New Features Thematic Map is a visualization that allows the user to see business data in geographical context. New features in 12.1.3 include: Area layer styling and marker zoom behavior: The new marker rotation feature: Ability to display isolated areas: Support for custom base maps: New Visualization: Diagram Diagram can be used to visualize different sets of data by displaying nodes and relationships between them. Diagram is currently available as a runtime-only component, and provides a pluggable framework for the application developers to define custom layouts in javascript. Design time for Diagram will be available in a future release. Diagram is a very powerful component that can be used to create very different visualizations, such as this arc Diagram: Stay tuned for more in-depth articles on working with Diagram from Oracle guru Duncan Mills, and more tips and tricks on working with the new Charts and other Data Visualizations.

Welcome to the Oracle Data Visualization blog! In this blog, you can expect to see articles on the latest features in Oracle Data Visualizations, tips and tricks for using the components, and more. Overv...

A Guide to Diagram – Introduction

The 12.1.3 release of Fusion Middleware sees the rather exciting introduction of the new DVT Diagram component.  I've been using diagram for some time now so it's great to be able to pass on some of my experiences in the form of a series of blog articles specifically about the component.  Before we dive into the details, let's get a high level picture of what diagram is all about.  In concept it's slightly different from your run-of-the-mill JSF component where all you do is to provide the data and set a few properties.  With diagram you may have a little more work to do, but the payback is a huge in terms of flexibility and power.  Starting With The Basics From a data perspective, diagram is pretty simple; it will take a collection of nodes that describe the shapes on the diagram (the boxes, diamonds, cloud and robots in the example screenshot below) and a collection of links that describe the edges (lines) that connect those shapes together. Unlike a tree or hierarchy viewer component there does not have to be any hierarchy in the data, relationships can run in any direction, and indeed there don't even need to be relationships. The third partner in the diagram story is the layout.  This highlights one of the big differences between diagram and many other ADF components.  We realized early on that it would be impossible to come up with a definitive list of all of the ways that developers might want to lay out the shapes and links on the diagram. Just imagine the possible combinations here you have here in the way that nodes are physically laid out and how far apart they are.  Given that you have a very open unstructured set of data there is really no "correct" way to do a layout. Inevitably if we had just come up with a set of common layouts they might work for a small percentage of the community but even more folks would be asking for different views or more configurability to what we already had. Every diagram is different! So the key point about the DVT diagram is that the layouts are not picked from a fixed set.  We ship a set of demo layouts that you can re-use, but in most cases we expect that you'll want to create your own. Rest assured, this is a topic that I'll be covering in some detail later in this series of articles.  The good news is that this ability to precisely control layout just makes the component even more useful and powerful! Here's a screen shot of one of the diagram demos, just to wet your appetite. This example embodies a classic diagram style of visualization, however, it's just the start of what you are able to acheive. What Diagram is Not Although the diagram can be interactive to a degree, for example it supports drag and drop, it is not a design surface.  Don't pick up diagram and expect to be able to move nodes around on the surface to random positions. It's primarily a visualization tool and although in the future you may be able to fully emulate a freeform vector graphics program with it, we're not there yet.  Saying that, with a little imagination, you can step way beyond simple visualization into something that works as an input device.  The Simple Rules Editor Demo is an example of this. The user of the page can build up complex expressions by dragging and dropping "facts" onto the diagram, which then displays a visual representation of the rule-set as it is being built. What the Diagram Can Show As you can see from some of the screen shots included in this article, there is quite a wide range of things that can be displayed on the diagram nodes.  They can just be simple shapes or images with a label, but they can also be more complex and like the hierarchy viewer, the nodes can contain differing amounts of information depending on the zoom level and also rich content on the nodes including the use of panelCards.  In a future article we'll be looking at the content of nodes in much more detail and covering all of the possibilties. Interactivity  You can go away and have a play for yourself with the online diagram demos at http://jdevadf.oracle.com to get a feel for the component in action, but the basics are simple.  The user can pan around the diagram using the mouse or the thumbnail view, and zoom, using the specialist zoom bar or mouse. Of course if the user is on a tablet then they can use their fingers with standard drag and pinch gestures to pan and zoom as well. The nodes in the diagram are also keyboard navigable if you don't use a mouse.   Diagram nodes themselves can be grouped and stacked in various ways, something that we'll cover in later articles, but when you click on a particular node you may well see an activity icon which allows you to carry out some additional operations.  Here's a quick summary for reference: Isolate Allows you to "zoom in" to just view this node (and it's containees) and hide all other nodes Additional Links When you have isolated a node clicking this icon will pull in other nodes that are directly linked to this node Restore When you have isolated a node, this icon appears at the top is the diagram and undoes the isolation, restoring the previous view Drill Used when nodes contain other nodes this icon allows you to drill into the container and just focus on it's contents.  The diagram renders a breadcrumb trail for you to navigate back up through the hierarchy. Delete if your diagram node is marked as editiable (ie. readOnly="false") then this icon will appear and will trigger the nodeDeleteListener associated with the diagram Preview Stack When several nodes of the same type are "stacked together", this icon will overlay an exploded version of the stack so that you can see the individual members Close Stack loses the preview overlay of the stacked node and returns back to the main diagram view Unstack Explodes the stack to show each node individually Control Panel Located in the top / left of the diagram clicking this icon will reveal or hide the zoom controls Overviewl Panel Located in the bottom / left of the diagram clicking this icon will reveal or hide the thumbnail view Legend Panel Located in the top / right of the diagram clicking this icon will reveal or hide the legend for the diagram Palette Panel Located in the top / right of the diagram clicking this icon will reveal or hide the palette that you can use for node types and links to drag onto an updatable diagram How it works  If you're curious about how the diagram is actually rendered in the page by all means, have a look with your browser's development tools.  In doing so you'll see that we actually transform the diagram into SVG within the HTML output. Being SVG we can do all of the scaling effectively as the user zooms in and out, but it also explains some of the restrictions of the diagram, such as the inability to use input components on the node (see the later article on Diagram Nodes).  When an ADF component is used on a diagram node it is actually rendered to the browser in a totally different way than it would be in the rest of the page, but of course that's not something you need to worry about. In the Next Article Hopefully this introductory article has ignited your interest in diagram and opened your mind to some of the potential uses for it within your applications.  In the next article in this series I'll start to look at diagram from the technical perspective, by looking at the basic data structures required to make diagram tick.Related Articles The Learning Diagram Series  Part 1 - Data For Nodes and Links

The 12.1.3 release of Fusion Middleware sees the rather exciting introduction of the new DVT Diagram component.  I've been using diagram for some time now so it's great to be able to pass on some of...