summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/base/debug/debug.scss217
-rw-r--r--WebContent/VAADIN/themes/base/debug/fonts/font.dev.svg39
-rw-r--r--WebContent/VAADIN/themes/base/debug/fonts/font.eotbin0 -> 6124 bytes
-rw-r--r--WebContent/VAADIN/themes/base/debug/fonts/font.svg39
-rw-r--r--WebContent/VAADIN/themes/base/debug/fonts/font.ttfbin0 -> 5944 bytes
-rw-r--r--WebContent/VAADIN/themes/base/debug/fonts/font.woffbin0 -> 3336 bytes
-rw-r--r--client/src/com/vaadin/Vaadin.gwt.xml2
-rw-r--r--client/src/com/vaadin/client/VDebugConsole.java6
-rw-r--r--client/src/com/vaadin/client/ValueMap.java4
-rw-r--r--client/src/com/vaadin/client/debug/internal/ConsoleAdapter.java183
-rw-r--r--client/src/com/vaadin/client/debug/internal/DebugButton.java109
-rw-r--r--client/src/com/vaadin/client/debug/internal/HierarchySection.java574
-rw-r--r--client/src/com/vaadin/client/debug/internal/Highlight.java185
-rw-r--r--client/src/com/vaadin/client/debug/internal/Icon.java46
-rw-r--r--client/src/com/vaadin/client/debug/internal/Level.java26
-rw-r--r--client/src/com/vaadin/client/debug/internal/LogSection.java318
-rw-r--r--client/src/com/vaadin/client/debug/internal/NetworkSection.java101
-rw-r--r--client/src/com/vaadin/client/debug/internal/Section.java78
-rw-r--r--client/src/com/vaadin/client/debug/internal/VDebugWindow.java1086
19 files changed, 3007 insertions, 6 deletions
diff --git a/WebContent/VAADIN/themes/base/debug/debug.scss b/WebContent/VAADIN/themes/base/debug/debug.scss
index b6d22e8433..687370270e 100644
--- a/WebContent/VAADIN/themes/base/debug/debug.scss
+++ b/WebContent/VAADIN/themes/base/debug/debug.scss
@@ -29,4 +29,221 @@
.v-app .invalidlayout * {
background: #f99 !important;
}
+
+ /* NEW debug window */
+ $mainbg: #fff;
+ $darkborder: #666;
+ $lightborder: #999;
+ $maincolor: #666;
+ $activecolor: #000;
+
+ @font-face {
+ font-family: 'vdebugfont';
+ src:url('fonts/font.eot');
+ src:url('fonts/font.eot?#iefix') format('embedded-opentype'),
+ url('fonts/font.woff') format('woff'),
+ url('fonts/font.ttf') format('truetype'),
+ url('fonts/font.svg#fontawesome') format('svg');
+ font-weight: normal;
+ font-style: normal;
+ }
+
+ .v-debugwindow [data-icon]:before,
+ .v-debugwindow-menu [data-icon]:before {
+ font-family: 'vdebugfont';
+ content: attr(data-icon);
+ speak: none;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ font-style: normal;
+ vertical-align: text-bottom;
+ }
+
+ .v-debugwindow {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+
+ -moz-opacity: 0.8;
+ -webkit-opacity: 0.8;
+ opacity: 0.8;
+ color: $maincolor;
+
+ font-size: 13px;
+ }
+ .v-debugwindow:hover {
+ -moz-opacity: 1;
+ -webkit-opacity: 1;
+ opacity: 1;
+ }
+ .v-debugwindow * {
+ font-size: inherit !important;
+ }
+
+ .v-debugwindow-size0, .v-debugwindow-menu .v-debugwindow-button-size0 {
+ font-size: 10px;
+ }
+ .v-debugwindow-size1, .v-debugwindow-menu .v-debugwindow-button-size1 {
+ font-size: 13px;
+ }
+ .v-debugwindow-size2, .v-debugwindow-menu .v-debugwindow-button-size2 {
+ font-size: 16px;
+ }
+
+ .v-debugwindow-head {
+ text-align: right;
+ cursor: move;
+ bakcground-color: transparent;
+ }
+
+ .v-debugwindow-tabs {
+ display: inline-block;
+ background-color: $mainbg;
+ }
+
+ .v-debugwindow-tab, .v-debugwindow-controls > * {
+ width: 2em;
+ border: none;
+ margin: 0;
+ line-height: 1.5em;
+ background-color: $mainbg;
+ color: $maincolor;
+ }
+ .v-debugwindow-tab {
+ position: relative;
+ top: 1px;
+ border-width: 1px 0 1px 1px;
+ border-style: solid;
+ border-color: $darkborder;
+ border-radius: 2px 2px 0 0;
+ }
+ .v-debugwindow-tab-selected {
+ color: $maincolor;
+ background-color: $mainbg;
+ border-bottom: 1px solid #fff;
+ }
+
+ .v-debugwindow-controls {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ background-color: $mainbg;
+ border: 1px solid $darkborder;
+ border-radius: 2px 2px 0 0;
+ }
+
+ .v-debugwindow-section-head {
+ text-align: left;
+ background-color: $mainbg;
+ border: 1px solid $darkborder;
+ border-bottom: 1px solid $lightborder;
+
+ box-shadow: 0px 0px 7px 0 rgba(55,55,55,0.6);
+ min-height: 1.5em;
+ }
+
+ .v-debugwindow-button {
+ border: none;
+ background-color: transparent;
+ color: $maincolor;
+ }
+ .v-debugwindow-button:hover {
+ color: $activecolor;
+ text-decoration: underline;
+ }
+ .v-debugwindow-button-active {
+ color: $maincolor;
+ box-shadow: 1px 1px 3px 0 inset;
+ }
+
+ .v-debugwindow-content {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+
+ box-shadow: 0px 0px 7px 0 rgba(55,55,55,0.6);
+
+ background-color: $mainbg;
+ border: 1px solid $darkborder;
+ border-top: none;
+
+ font-family: monospace;
+ }
+
+ .v-debugwindow-menu {
+ background-color: $mainbg;
+ padding: 4px;
+ border: 1px solid $lightborder;
+ border-top: none;
+
+ border-radius: 0 0 5px 5px;
+
+ box-shadow: 0px 0px 7px 0 rgba(55,55,55,0.6);
+ }
+ .v-debugwindow-menu-content {
+ min-width: 100px;
+ }
+ .v-debugwindow-menu-content .v-debugwindow-button {
+ line-height: 22px;
+ }
+ .v-debugwindow-menu-content > div > .v-debugwindow-button {
+ width: 33%;
+ }
+
+
+ /* LOG */
+ .v-debugwindow-reset {
+ color: #fff;
+ background-color: #4C92ED;
+ padding: 4px;
+ }
+
+ .v-debugwindow-row {
+ display: table-row;
+ }
+ .v-debugwindow-row:nth-child(odd) {
+ background-color: rgba(0, 61, 255, 0.11);
+ }
+ .v-debugwindow-row.ERROR {
+ color: #550000;
+ background-color: #FFC5C5;
+ }
+ .v-debugwindow-row.WARNING {
+ background-color: #FFFF99;
+ }
+
+ .v-debugwindow-row > span {
+ display: table-cell;
+ padding: 4px;
+ }
+
+ .v-debugwindow-time {
+ text-align: right;
+ color: #999;
+ }
+ .v-debugwindow-message {
+ white-space: nowrap;
+ width: 100%
+ }
+ .v-debugwindow-message:hover {
+ white-space: normal;
+ word-wrap: break-word;
+ }
+ .v-debugwindow-message em {
+ background-color: #C4E6F8;
+ }
+
+ /* HIERARCHY */
+ .v-debugwindow-row > span.caption {
+ color: #999;
+ text-align: right;
+ white-space: nowrap;
+ }
+ .v-debugwindow-row > span.value {
+ width: 100%;
+ }
+
} \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/base/debug/fonts/font.dev.svg b/WebContent/VAADIN/themes/base/debug/fonts/font.dev.svg
new file mode 100644
index 0000000000..24fa9ceeed
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/debug/fonts/font.dev.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="14"></iconset>
+</metadata>
+<defs>
+<font id="fontawesome" horiz-adv-x="448" >
+<font-face units-per-em="448" ascent="384" descent="-64" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode="&#xf002;" d="M 288.00,176.00q0.00,46.25 -32.875,79.125t-79.125,32.875t-79.125-32.875t-32.875-79.125t 32.875-79.125t 79.125-32.875t 79.125,32.875t 32.875,79.125zM 416.00-32.00q0.00-13.00 -9.50-22.50t-22.50-9.50q-13.50,0.00 -22.50,9.50l-85.75,85.50q-44.75-31.00 -99.75-31.00q-35.75,0.00 -68.375,13.875t-56.25,37.50t-37.50,56.25t-13.875,68.375 t 13.875,68.375t 37.50,56.25t 56.25,37.50t 68.375,13.875t 68.375-13.875t 56.25-37.50t 37.50-56.25t 13.875-68.375q0.00-55.00 -31.00-99.75l 85.75-85.75q 9.25-9.25 9.25-22.50z" horiz-adv-x="416" data-tags="search, magnifier, lookup, find" />
+<glyph unicode="&#xf00c;" d="M 417.75,242.50q0.00-10.00 -7.00-17.00l-181.00-181.00l-34.00-34.00q-7.00-7.00 -17.00-7.00t-17.00,7.00l-34.00,34.00l-90.50,90.50q-7.00,7.00 -7.00,17.00t 7.00,17.00l 34.00,34.00q 7.00,7.00 17.00,7.00t 17.00-7.00l 73.50-73.75l 164.00,164.25q 7.00,7.00 17.00,7.00t 17.00-7.00l 34.00-34.00q 7.00-7.00 7.00-17.00z" data-tags="ok, checkmark, tick, correct" />
+<glyph unicode="&#xf00d;" d="M 324.50,53.50q0.00-10.00 -7.00-17.00l-34.00-34.00q-7.00-7.00 -17.00-7.00t-17.00,7.00l-73.50,73.50l-73.50-73.50q-7.00-7.00 -17.00-7.00t-17.00,7.00l-34.00,34.00q-7.00,7.00 -7.00,17.00t 7.00,17.00l 73.50,73.50l-73.50,73.50q-7.00,7.00 -7.00,17.00t 7.00,17.00l 34.00,34.00q 7.00,7.00 17.00,7.00t 17.00-7.00l 73.50-73.50l 73.50,73.50q 7.00,7.00 17.00,7.00t 17.00-7.00l 34.00-34.00q 7.00-7.00 7.00-17.00 t-7.00-17.00l-73.50-73.50l 73.50-73.50q 7.00-7.00 7.00-17.00z" horiz-adv-x="352" data-tags="remove, cancel, close, delete, mutiply" />
+<glyph unicode="&#xf011;" d="M 384.00,160.00q0.00-39.00 -15.25-74.50t-41.00-61.25t-61.25-41.00t-74.50-15.25t-74.50,15.25t-61.25,41.00t-41.00,61.25t-15.25,74.50q0.00,45.50 20.125,85.75t 56.625,67.50q 10.75,8.00 23.875,6.25t 20.875-12.50q 8.00-10.50 6.125-23.625t-12.375-21.125q-24.50-18.50 -37.875-45.25t-13.375-57.00q0.00-26.00 10.125-49.625t 27.375-40.875t 40.875-27.375 t 49.625-10.125t 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625q0.00,30.25 -13.375,57.00t-37.875,45.25q-10.50,8.00 -12.375,21.125t 6.125,23.625q 7.75,10.75 21.00,12.50t 23.75-6.25q 36.50-27.25 56.625-67.50t 20.125-85.75zM 224.00,352.00l0.00-160.00 q0.00-13.00 -9.50-22.50t-22.50-9.50t-22.50,9.50t-9.50,22.50l0.00,160.00 q0.00,13.00 9.50,22.50t 22.50,9.50t 22.50-9.50t 9.50-22.50z" horiz-adv-x="384" data-tags="off, switch, power" />
+<glyph unicode="&#xf014;" d="M 128.00,200.00l0.00-144.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-16.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,144.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 16.00,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75zM 192.00,200.00l0.00-144.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-16.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,144.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 16.00,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75zM 256.00,200.00l0.00-144.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-16.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,144.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 16.00,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75zM 288.00,19.00l0.00,237.00 l-224.00,0.00 l0.00-237.00 q0.00-5.50 1.75-10.125t 3.625-6.75t 2.625-2.125l 208.00,0.00 q 0.75,0.00 2.625,2.125t 3.625,6.75t 1.75,10.125zM 120.00,288.00l 112.00,0.00 l-12.00,29.25q-1.75,2.25 -4.25,2.75l-79.25,0.00 q-2.50-0.50 -4.25-2.75zM 352.00,280.00l0.00-16.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-24.00,0.00 l0.00-237.00 q0.00-20.75 -11.75-35.875t-28.25-15.125l-208.00,0.00 q-16.50,0.00 -28.25,14.625t-11.75,35.375l0.00,238.00 l-24.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,16.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 77.25,0.00 l 17.50,41.75q 3.75,9.25 13.50,15.75t 19.75,6.50l 80.00,0.00 q 10.00,0.00 19.75-6.50t 13.50-15.75l 17.50-41.75l 77.25,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75z" horiz-adv-x="352" data-tags="trash, remove, delete, bin" />
+<glyph unicode="&#xf017;" d="M 272.00,152.00l0.00-16.00 q0.00-3.25 -2.375-5.625t-5.625-2.375l-96.00,0.00 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,112.00 q0.00,3.25 2.375,5.625t 5.625,2.375l 16.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625l0.00-88.00 l 72.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625zM 320.00,160.00q0.00,26.00 -10.125,49.625t-27.375,40.875t-40.875,27.375t-49.625,10.125t-49.625-10.125 t-40.875-27.375t-27.375-40.875t-10.125-49.625t 10.125-49.625t 27.375-40.875t 40.875-27.375t 49.625-10.125t 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625zM 384.00,160.00q0.00-52.25 -25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875 t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" data-tags="time, clock" />
+<glyph unicode="&#xf066;" d="M 192.00,144.00l0.00-112.00 q0.00-6.50 -4.75-11.25t-11.25-4.75t-11.25,4.75l-36.00,36.00l-83.00-83.00q-2.50-2.50 -5.75-2.50t-5.75,2.50l-28.50,28.50q-2.50,2.50 -2.50,5.75t 2.50,5.75l 83.00,83.00l-36.00,36.00q-4.75,4.75 -4.75,11.25t 4.75,11.25t 11.25,4.75l 112.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 380.75,312.00q0.00-3.25 -2.50-5.75l-83.00-83.00l 36.00-36.00q 4.75-4.75 4.75-11.25t-4.75-11.25 t-11.25-4.75l-112.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,112.00 q0.00,6.50 4.75,11.25t 11.25,4.75t 11.25-4.75l 36.00-36.00l 83.00,83.00q 2.50,2.50 5.75,2.50t 5.75-2.50l 28.50-28.50q 2.50-2.50 2.50-5.75z" horiz-adv-x="384" data-tags="resize-small, contract, collapse" />
+<glyph unicode="&#xf071;" d="M 256.00,40.25l0.00,47.50 q0.00,3.50 -2.375,5.875t-5.625,2.375l-48.00,0.00 q-3.25,0.00 -5.625-2.375t-2.375-5.875l0.00-47.50 q0.00-3.50 2.375-5.875t 5.625-2.375l 48.00,0.00 q 3.25,0.00 5.625,2.375t 2.375,5.875zM 255.50,133.75l 4.50,114.75q0.00,3.00 -2.50,4.75q-3.25,2.75 -6.00,2.75l-55.00,0.00 q-2.75,0.00 -6.00-2.75q-2.50-1.75 -2.50-5.25l 4.25-114.25q0.00-2.50 2.50-4.125t 6.00-1.625l 46.25,0.00 q 3.50,0.00 5.875,1.625t 2.625,4.125zM 252.00,367.25l 192.00-352.00q 8.75-15.75 -0.50-31.50q-4.25-7.25 -11.625-11.50t-15.875-4.25l-384.00,0.00 q-8.50,0.00 -15.875,4.25t-11.625,11.50q-9.25,15.75 -0.50,31.50l 192.00,352.00q 4.25,7.75 11.75,12.25t 16.25,4.50t 16.25-4.50t 11.75-12.25z" data-tags="warning-sign, sign" />
+<glyph unicode="&#xf05a;" d="M 256.00,40.00l0.00,16.00 q0.00,3.50 -2.25,5.75t-5.75,2.25l-24.00,0.00 l0.00,120.00 q0.00,3.50 -2.25,5.75t-5.75,2.25l-80.00,0.00 q-3.50,0.00 -5.75-2.25t-2.25-5.75l0.00-16.00 q0.00-3.50 2.25-5.75t 5.75-2.25l 24.00,0.00 l0.00-96.00 l-24.00,0.00 q-3.50,0.00 -5.75-2.25t-2.25-5.75l0.00-16.00 q0.00-3.50 2.25-5.75t 5.75-2.25l 112.00,0.00 q 3.50,0.00 5.75,2.25t 2.25,5.75zM 224.00,232.00l0.00,48.00 q0.00,3.50 -2.25,5.75t-5.75,2.25l-48.00,0.00 q-3.50,0.00 -5.75-2.25t-2.25-5.75l0.00-48.00 q0.00-3.50 2.25-5.75 t 5.75-2.25l 48.00,0.00 q 3.50,0.00 5.75,2.25t 2.25,5.75zM 384.00,160.00q0.00-52.25 -25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" data-tags="info-sign, information, sign" />
+<glyph unicode="&#xf06a;" d="M 192.00,352.00q 52.25,0.00 96.375-25.75t 69.875-69.875t 25.75-96.375t-25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75zM 224.00,40.25l0.00,47.50 q0.00,3.50 -2.25,5.875t-5.50,2.375l-48.00,0.00 q-3.25,0.00 -5.75-2.50t-2.50-5.75l0.00-47.50 q0.00-3.25 2.50-5.75t 5.75-2.50l 48.00,0.00 q 3.25,0.00 5.50,2.375t 2.25,5.875zM 223.50,126.25l 4.50,155.25q0.00,3.00 -2.50,4.50q-2.50,2.00 -6.00,2.00l-55.00,0.00 q-3.50,0.00 -6.00-2.00q-2.50-1.50 -2.50-4.50l 4.25-155.25q0.00-2.50 2.50-4.375t 6.00-1.875l 46.25,0.00 q 3.50,0.00 5.875,1.875t 2.625,4.375z" horiz-adv-x="384" data-tags="exclamation-sign, sign, notification, attention, warning" />
+<glyph unicode="&#xf05b;" d="M 299.25,128.00l-27.25,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 27.25,0.00 q-8.00,27.00 -28.125,47.125t-47.125,28.125l0.00-27.25 q0.00-6.50 -4.75-11.25t-11.25-4.75l-32.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,27.25 q-27.00-8.00 -47.125-28.125t-28.125-47.125l 27.25,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-27.25,0.00 q 8.00-27.00 28.125-47.125t 47.125-28.125l0.00,27.25 q0.00,6.50 4.75,11.25t 11.25,4.75l 32.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25l0.00-27.25 q 27.00,8.00 47.125,28.125t 28.125,47.125zM 384.00,176.00l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-35.75,0.00 q-9.25-40.25 -38.625-69.625t-69.625-38.625l0.00-35.75 q0.00-6.50 -4.75-11.25t-11.25-4.75l-32.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,35.75 q-40.25,9.25 -69.625,38.625t-38.625,69.625l-35.75,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 35.75,0.00 q 9.25,40.25 38.625,69.625t 69.625,38.625l0.00,35.75 q0.00,6.50 4.75,11.25t 11.25,4.75l 32.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25l0.00-35.75 q 40.25-9.25 69.625-38.625t 38.625-69.625l 35.75,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" data-tags="screenshot, target, goal, spot" />
+<glyph unicode="&#xf0c9;" d="M 384.00,48.00l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-352.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 352.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 384.00,176.00l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-352.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 352.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 384.00,304.00l0.00-32.00 q0.00-6.50 -4.75-11.25 t-11.25-4.75l-352.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 352.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" data-tags="reorder, list, menu" />
+<glyph unicode="&#xf0d0;" d="M 297.50,238.75l 73.25,73.25l-26.75,26.75l-73.25-73.25zM 409.25,312.00q0.00-6.75 -4.50-11.25l-321.50-321.50q-4.50-4.50 -11.25-4.50t-11.25,4.50l-49.50,49.50q-4.50,4.50 -4.50,11.25t 4.50,11.25l 321.50,321.50q 4.50,4.50 11.25,4.50t 11.25-4.50l 49.50-49.50q 4.50-4.50 4.50-11.25zM 71.50,359.50l 24.50-7.50l-24.50-7.50l-7.50-24.50l-7.50,24.50l-24.50,7.50l 24.50,7.50l 7.50,24.50zM 159.00,319.00 l 49.00-15.00l-49.00-15.00l-15.00-49.00l-15.00,49.00l-49.00,15.00l 49.00,15.00l 15.00,49.00zM 391.50,199.50l 24.50-7.50l-24.50-7.50l-7.50-24.50l-7.50,24.50l-24.50,7.50l 24.50,7.50l 7.50,24.50zM 231.50,359.50l 24.50-7.50l-24.50-7.50l-7.50-24.50l-7.50,24.50l-24.50,7.50l 24.50,7.50l 7.50,24.50z" horiz-adv-x="416" data-tags="magic, wand, wizard" />
+<glyph unicode="&#xf0e8;" d="M 448.00,72.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-80.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 24.00,0.00 l0.00,48.00 l-128.00,0.00 l0.00-48.00 l 24.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-80.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 24.00,0.00 l0.00,48.00 l-128.00,0.00 l0.00-48.00 l 24.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-80.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 24.00,0.00 l0.00,48.00 q0.00,13.00 9.50,22.50t 22.50,9.50l 128.00,0.00 l0.00,48.00 l-24.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 80.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-24.00,0.00 l0.00-48.00 l 128.00,0.00 q 13.00,0.00 22.50-9.50t 9.50-22.50l0.00-48.00 l 24.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00 z" data-tags="sitemap, tree" />
+<glyph unicode="&#xf013;" d="M 256.00,160.00q0.00,26.50 -18.75,45.25t-45.25,18.75t-45.25-18.75t-18.75-45.25t 18.75-45.25t 45.25-18.75t 45.25,18.75t 18.75,45.25zM 384.00,187.25l0.00-55.50 q0.00-3.00 -2.00-5.75t-5.00-3.25l-46.25-7.00q-4.75-13.50 -9.75-22.75q 8.75-12.50 26.75-34.50q 2.50-3.00 2.50-6.25t-2.25-5.75q-6.75-9.25 -24.75-27.00t-23.50-17.75q-3.00,0.00 -6.50,2.25l-34.50,27.00q-11.00-5.75 -22.75-9.50 q-4.00-34.00 -7.25-46.50q-1.75-7.00 -9.00-7.00l-55.50,0.00 q-3.50,0.00 -6.125,2.125t-2.875,5.375l-7.00,46.00q-12.25,4.00 -22.50,9.25l-35.25-26.75q-2.50-2.25 -6.25-2.25q-3.50,0.00 -6.25,2.75q-31.50,28.50 -41.25,42.00q-1.75,2.50 -1.75,5.75q0.00,3.00 2.00,5.75q 3.75,5.25 12.75,16.625t 13.50,17.625q-6.75,12.50 -10.25,24.75l-45.75,6.75q-3.25,0.50 -5.25,3.125t-2.00,5.875l0.00,55.50 q0.00,3.00 2.00,5.75t 4.75,3.25 l 46.50,7.00q 3.50,11.50 9.75,23.00q-10.00,14.25 -26.75,34.50q-2.50,3.00 -2.50,6.00q0.00,2.50 2.25,5.75q 6.50,9.00 24.625,26.875t 23.625,17.875q 3.25,0.00 6.50-2.50l 34.50-26.75q 11.00,5.75 22.75,9.50q 4.00,34.00 7.25,46.50q 1.75,7.00 9.00,7.00l 55.50,0.00 q 3.50,0.00 6.125-2.125t 2.875-5.375l 7.00-46.00q 12.25-4.00 22.50-9.25l 35.50,26.75q 2.25,2.25 6.00,2.25q 3.25,0.00 6.25-2.50q 32.25-29.75 41.25-42.50q 1.75-2.00 1.75-5.50 q0.00-3.00 -2.00-5.75q-3.75-5.25 -12.75-16.625t-13.50-17.625q 6.50-12.50 10.25-24.50l 45.75-7.00q 3.25-0.50 5.25-3.125t 2.00-5.875z" horiz-adv-x="384" data-tags="cog, settings, options, gear, preferences" />
+<glyph unicode="&#xf0ec;" d="M 448.00,88.00l0.00-48.00 q0.00-3.25 -2.375-5.625t-5.625-2.375l-344.00,0.00 l0.00-48.00 q0.00-3.25 -2.375-5.625t-5.625-2.375q-3.00,0.00 -6.00,2.50l-79.75,80.00q-2.25,2.25 -2.25,5.50q0.00,3.50 2.25,5.75l 80.00,80.00q 2.25,2.25 5.75,2.25q 3.25,0.00 5.625-2.375t 2.375-5.625l0.00-48.00 l 344.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625zM 448.00,224.00q0.00-3.50 -2.25-5.75l-80.00-80.00q-2.25-2.25 -5.75-2.25 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,48.00 l-344.00,0.00 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,48.00 q0.00,3.25 2.375,5.625t 5.625,2.375l 344.00,0.00 l0.00,48.00 q0.00,3.50 2.25,5.75t 5.75,2.25q 3.00,0.00 6.00-2.50l 79.75-79.75q 2.25-2.25 2.25-5.75z" data-tags="exchange, transfer, tab, traffic" />
+<glyph unicode="&#xf0f0;" d="M 96.00,48.00q0.00-6.50 -4.75-11.25t-11.25-4.75t-11.25,4.75t-4.75,11.25t 4.75,11.25t 11.25,4.75t 11.25-4.75t 4.75-11.25zM 352.00,32.75q0.00-30.25 -18.25-47.50t-48.50-17.25l-218.50,0.00 q-30.25,0.00 -48.50,17.25t-18.25,47.50q0.00,17.00 1.375,32.75t 6.00,34.50t 11.875,33.125t 20.25,25.75t 30.00,15.125q-5.50-13.00 -5.50-30.00l0.00-50.75 q-14.50-5.00 -23.25-17.50t-8.75-27.75q0.00-20.00 14.00-34.00t 34.00-14.00 t 34.00,14.00t 14.00,34.00q0.00,15.25 -8.875,27.75t-23.125,17.50l0.00,50.75 q0.00,15.50 6.25,23.25q 33.00-26.00 73.75-26.00t 73.75,26.00q 6.25-7.75 6.25-23.25l0.00-16.00 q-26.50,0.00 -45.25-18.75t-18.75-45.25l0.00-22.25 q-8.00-7.25 -8.00-17.75q0.00-10.00 7.00-17.00t 17.00-7.00t 17.00,7.00t 7.00,17.00q0.00,10.50 -8.00,17.75l0.00,22.25 q0.00,13.00 9.50,22.50t 22.50,9.50t 22.50-9.50t 9.50-22.50l0.00-22.25 q-8.00-7.25 -8.00-17.75q0.00-10.00 7.00-17.00 t 17.00-7.00t 17.00,7.00t 7.00,17.00q0.00,10.50 -8.00,17.75l0.00,22.25 q0.00,17.00 -8.625,31.875t-23.375,23.375q0.00,2.50 0.125,10.625t0.00,12.00t-0.625,10.375t-1.75,11.75t-3.25,10.00q 17.00-3.75 30.00-15.125t 20.25-25.75t 11.875-33.125t 6.00-34.50t 1.375-32.75zM 272.00,256.00q0.00-39.75 -28.125-67.875t-67.875-28.125t-67.875,28.125t-28.125,67.875t 28.125,67.875t 67.875,28.125 t 67.875-28.125t 28.125-67.875z" horiz-adv-x="352" data-tags="user-md, medic, doctor" />
+<glyph unicode="&#xf023;" d="M 176.00,128.00q0.00,13.25 -9.375,22.625t-22.625,9.375t-22.625-9.375t-9.375-22.625q0.00-9.25 4.75-16.75t 12.75-11.75l-17.25-57.25q-1.25-3.75 1.25-7.00t 6.50-3.25l 48.00,0.00 q 4.00,0.00 6.50,3.25t 1.25,7.00l-17.25,57.25q 8.00,4.25 12.75,11.75t 4.75,16.75zM 80.00,192.00l 128.00,0.00 l0.00,48.00 q0.00,26.50 -18.75,45.25t-45.25,18.75t-45.25-18.75t-18.75-45.25l0.00-48.00 zM 288.00,168.00l0.00-144.00 q0.00-10.00 -7.00-17.00 t-17.00-7.00l-240.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,144.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 8.00,0.00 l0.00,48.00 q0.00,46.00 33.00,79.00t 79.00,33.00t 79.00-33.00t 33.00-79.00l0.00-48.00 l 8.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00z" horiz-adv-x="288" data-tags="lock, password, secure, private, protected, encrypted" />
+<glyph unicode="&#xf10c;" d="M 320.00,160.00q0.00,26.00 -10.125,49.625t-27.375,40.875t-40.875,27.375t-49.625,10.125t-49.625-10.125t-40.875-27.375t-27.375-40.875t-10.125-49.625t 10.125-49.625t 27.375-40.875t 40.875-27.375t 49.625-10.125t 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625zM 384.00,160.00q0.00-52.25 -25.75-96.375 t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" data-tags="circle-blank" />
+<glyph unicode="&#xf111;" d="M 384.00,160.00q0.00-52.25 -25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" data-tags="circle" />
+<glyph unicode="&#xf110;" d="M 124.00,48.00q0.00-15.00 -10.625-25.50t-25.375-10.50q-15.00,0.00 -25.50,10.50t-10.50,25.50t 10.50,25.50t 25.50,10.50q 14.75,0.00 25.375-10.50t 10.625-25.50zM 232.00,0.00q0.00-13.25 -9.375-22.625t-22.625-9.375t-22.625,9.375t-9.375,22.625t 9.375,22.625t 22.625,9.375t 22.625-9.375t 9.375-22.625zM 80.00,160.00q0.00-16.50 -11.75-28.25t-28.25-11.75t-28.25,11.75t-11.75,28.25 t 11.75,28.25t 28.25,11.75t 28.25-11.75t 11.75-28.25zM 340.00,48.00q0.00-11.50 -8.25-19.75t-19.75-8.25t-19.75,8.25t-8.25,19.75t 8.25,19.75t 19.75,8.25t 19.75-8.25t 8.25-19.75zM 132.00,272.00q0.00-18.25 -12.875-31.125t-31.125-12.875t-31.125,12.875t-12.875,31.125t 12.875,31.125t 31.125,12.875t 31.125-12.875t 12.875-31.125zM 248.00,320.00q0.00-20.00 -14.00-34.00t-34.00-14.00 t-34.00,14.00t-14.00,34.00t 14.00,34.00t 34.00,14.00t 34.00-14.00t 14.00-34.00zM 384.00,160.00q0.00-10.00 -7.00-17.00t-17.00-7.00t-17.00,7.00t-7.00,17.00t 7.00,17.00t 17.00,7.00t 17.00-7.00t 7.00-17.00zM 332.00,272.00q0.00-8.25 -5.875-14.125t-14.125-5.875t-14.125,5.875t-5.875,14.125t 5.875,14.125t 14.125,5.875t 14.125-5.875t 5.875-14.125z" horiz-adv-x="392" data-tags="spinner, loading, busy, progress" />
+<glyph unicode="&#xf05e;" d="M 320.00,160.00q0.00,34.75 -17.75,65.00l-175.25-175.25q 30.25-17.75 65.00-17.75q 26.00,0.00 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625zM 81.75,95.00l 175.25,175.25q-30.25,17.75 -65.00,17.75q-26.00,0.00 -49.625-10.125t-40.875-27.375t-27.375-40.875t-10.125-49.625q0.00-34.75 17.75-65.00zM 384.00,160.00q0.00-52.25 -25.75-96.375 t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" data-tags="ban-circle, block, forbidden" />
+<glyph unicode="&#xf065;" d="M 188.75,120.00q0.00-3.25 -2.50-5.75l-83.00-83.00l 36.00-36.00q 4.75-4.75 4.75-11.25t-4.75-11.25t-11.25-4.75l-112.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,112.00 q0.00,6.50 4.75,11.25t 11.25,4.75t 11.25-4.75l 36.00-36.00l 83.00,83.00q 2.50,2.50 5.75,2.50t 5.75-2.50l 28.50-28.50q 2.50-2.50 2.50-5.75zM 384.00,336.00l0.00-112.00 q0.00-6.50 -4.75-11.25t-11.25-4.75t-11.25,4.75l-36.00,36.00l-83.00-83.00 q-2.50-2.50 -5.75-2.50t-5.75,2.50l-28.50,28.50q-2.50,2.50 -2.50,5.75t 2.50,5.75l 83.00,83.00l-36.00,36.00q-4.75,4.75 -4.75,11.25t 4.75,11.25t 11.25,4.75l 112.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" data-tags="resize-full, expand, enlarge" />
+<glyph unicode="&#xf021;" d="M 377.75,120.00q0.00-1.25 -0.25-1.75q-16.00-67.00 -67.00-108.625t-119.50-41.625q-36.50,0.00 -70.625,13.75t-60.875,39.25l-32.25-32.25q-4.75-4.75 -11.25-4.75t-11.25,4.75t-4.75,11.25l0.00,112.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 112.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25t-4.75-11.25l-34.25-34.25q 17.75-16.50 40.25-25.50t 46.75-9.00q 33.50,0.00 62.50,16.25t 46.50,44.75q 2.75,4.25 13.25,29.25 q 2.00,5.75 7.50,5.75l 48.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625zM 384.00,320.00l0.00-112.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-112.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25t 4.75,11.25l 34.50,34.50q-37.00,34.25 -87.25,34.25q-33.50,0.00 -62.50-16.25t-46.50-44.75q-2.75-4.25 -13.25-29.25q-2.00-5.75 -7.50-5.75l-49.75,0.00 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,1.75 q 16.25,67.00 67.50,108.625t 120.00,41.625 q 36.50,0.00 71.00-13.875t 61.25-39.125l 32.50,32.25q 4.75,4.75 11.25,4.75t 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" data-tags="refresh, synchronize" />
+<glyph unicode="&#xf02e;" d="M 291.00,352.00q 5.75,0.00 11.00-2.25q 8.25-3.25 13.125-10.25t 4.875-15.50l0.00-322.25 q0.00-8.50 -4.875-15.50t-13.125-10.25q-4.75-2.00 -11.00-2.00q-12.00,0.00 -20.75,8.00l-110.25,106.00l-110.25-106.00q-9.00-8.25 -20.75-8.25q-5.75,0.00 -11.00,2.25q-8.25,3.25 -13.125,10.25t-4.875,15.50l0.00,322.25 q0.00,8.50 4.875,15.50t 13.125,10.25q 5.25,2.25 11.00,2.25l 262.00,0.00 z" horiz-adv-x="320" data-tags="bookmark, favorite, ribbon" />
+<glyph unicode="&#x20;" horiz-adv-x="224" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,384L 448 -64L0 -64 z" horiz-adv-x="0" />
+</font></defs></svg> \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/base/debug/fonts/font.eot b/WebContent/VAADIN/themes/base/debug/fonts/font.eot
new file mode 100644
index 0000000000..310a74dfce
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/debug/fonts/font.eot
Binary files differ
diff --git a/WebContent/VAADIN/themes/base/debug/fonts/font.svg b/WebContent/VAADIN/themes/base/debug/fonts/font.svg
new file mode 100644
index 0000000000..8149b583fd
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/debug/fonts/font.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="14"></iconset>
+</metadata>
+<defs>
+<font id="fontawesome" horiz-adv-x="448" >
+<font-face units-per-em="448" ascent="384" descent="-64" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode="&#xf002;" d="M 288.00,176.00q0.00,46.25 -32.875,79.125t-79.125,32.875t-79.125-32.875t-32.875-79.125t 32.875-79.125t 79.125-32.875t 79.125,32.875t 32.875,79.125zM 416.00-32.00q0.00-13.00 -9.50-22.50t-22.50-9.50q-13.50,0.00 -22.50,9.50l-85.75,85.50q-44.75-31.00 -99.75-31.00q-35.75,0.00 -68.375,13.875t-56.25,37.50t-37.50,56.25t-13.875,68.375 t 13.875,68.375t 37.50,56.25t 56.25,37.50t 68.375,13.875t 68.375-13.875t 56.25-37.50t 37.50-56.25t 13.875-68.375q0.00-55.00 -31.00-99.75l 85.75-85.75q 9.25-9.25 9.25-22.50z" horiz-adv-x="416" />
+<glyph unicode="&#xf00c;" d="M 417.75,242.50q0.00-10.00 -7.00-17.00l-181.00-181.00l-34.00-34.00q-7.00-7.00 -17.00-7.00t-17.00,7.00l-34.00,34.00l-90.50,90.50q-7.00,7.00 -7.00,17.00t 7.00,17.00l 34.00,34.00q 7.00,7.00 17.00,7.00t 17.00-7.00l 73.50-73.75l 164.00,164.25q 7.00,7.00 17.00,7.00t 17.00-7.00l 34.00-34.00q 7.00-7.00 7.00-17.00z" />
+<glyph unicode="&#xf00d;" d="M 324.50,53.50q0.00-10.00 -7.00-17.00l-34.00-34.00q-7.00-7.00 -17.00-7.00t-17.00,7.00l-73.50,73.50l-73.50-73.50q-7.00-7.00 -17.00-7.00t-17.00,7.00l-34.00,34.00q-7.00,7.00 -7.00,17.00t 7.00,17.00l 73.50,73.50l-73.50,73.50q-7.00,7.00 -7.00,17.00t 7.00,17.00l 34.00,34.00q 7.00,7.00 17.00,7.00t 17.00-7.00l 73.50-73.50l 73.50,73.50q 7.00,7.00 17.00,7.00t 17.00-7.00l 34.00-34.00q 7.00-7.00 7.00-17.00 t-7.00-17.00l-73.50-73.50l 73.50-73.50q 7.00-7.00 7.00-17.00z" horiz-adv-x="352" />
+<glyph unicode="&#xf011;" d="M 384.00,160.00q0.00-39.00 -15.25-74.50t-41.00-61.25t-61.25-41.00t-74.50-15.25t-74.50,15.25t-61.25,41.00t-41.00,61.25t-15.25,74.50q0.00,45.50 20.125,85.75t 56.625,67.50q 10.75,8.00 23.875,6.25t 20.875-12.50q 8.00-10.50 6.125-23.625t-12.375-21.125q-24.50-18.50 -37.875-45.25t-13.375-57.00q0.00-26.00 10.125-49.625t 27.375-40.875t 40.875-27.375 t 49.625-10.125t 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625q0.00,30.25 -13.375,57.00t-37.875,45.25q-10.50,8.00 -12.375,21.125t 6.125,23.625q 7.75,10.75 21.00,12.50t 23.75-6.25q 36.50-27.25 56.625-67.50t 20.125-85.75zM 224.00,352.00l0.00-160.00 q0.00-13.00 -9.50-22.50t-22.50-9.50t-22.50,9.50t-9.50,22.50l0.00,160.00 q0.00,13.00 9.50,22.50t 22.50,9.50t 22.50-9.50t 9.50-22.50z" horiz-adv-x="384" />
+<glyph unicode="&#xf014;" d="M 128.00,200.00l0.00-144.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-16.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,144.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 16.00,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75zM 192.00,200.00l0.00-144.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-16.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,144.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 16.00,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75zM 256.00,200.00l0.00-144.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-16.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,144.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 16.00,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75zM 288.00,19.00l0.00,237.00 l-224.00,0.00 l0.00-237.00 q0.00-5.50 1.75-10.125t 3.625-6.75t 2.625-2.125l 208.00,0.00 q 0.75,0.00 2.625,2.125t 3.625,6.75t 1.75,10.125zM 120.00,288.00l 112.00,0.00 l-12.00,29.25q-1.75,2.25 -4.25,2.75l-79.25,0.00 q-2.50-0.50 -4.25-2.75zM 352.00,280.00l0.00-16.00 q0.00-3.50 -2.25-5.75t-5.75-2.25l-24.00,0.00 l0.00-237.00 q0.00-20.75 -11.75-35.875t-28.25-15.125l-208.00,0.00 q-16.50,0.00 -28.25,14.625t-11.75,35.375l0.00,238.00 l-24.00,0.00 q-3.50,0.00 -5.75,2.25t-2.25,5.75l0.00,16.00 q0.00,3.50 2.25,5.75t 5.75,2.25l 77.25,0.00 l 17.50,41.75q 3.75,9.25 13.50,15.75t 19.75,6.50l 80.00,0.00 q 10.00,0.00 19.75-6.50t 13.50-15.75l 17.50-41.75l 77.25,0.00 q 3.50,0.00 5.75-2.25t 2.25-5.75z" horiz-adv-x="352" />
+<glyph unicode="&#xf017;" d="M 272.00,152.00l0.00-16.00 q0.00-3.25 -2.375-5.625t-5.625-2.375l-96.00,0.00 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,112.00 q0.00,3.25 2.375,5.625t 5.625,2.375l 16.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625l0.00-88.00 l 72.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625zM 320.00,160.00q0.00,26.00 -10.125,49.625t-27.375,40.875t-40.875,27.375t-49.625,10.125t-49.625-10.125 t-40.875-27.375t-27.375-40.875t-10.125-49.625t 10.125-49.625t 27.375-40.875t 40.875-27.375t 49.625-10.125t 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625zM 384.00,160.00q0.00-52.25 -25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875 t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" />
+<glyph unicode="&#xf066;" d="M 192.00,144.00l0.00-112.00 q0.00-6.50 -4.75-11.25t-11.25-4.75t-11.25,4.75l-36.00,36.00l-83.00-83.00q-2.50-2.50 -5.75-2.50t-5.75,2.50l-28.50,28.50q-2.50,2.50 -2.50,5.75t 2.50,5.75l 83.00,83.00l-36.00,36.00q-4.75,4.75 -4.75,11.25t 4.75,11.25t 11.25,4.75l 112.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 380.75,312.00q0.00-3.25 -2.50-5.75l-83.00-83.00l 36.00-36.00q 4.75-4.75 4.75-11.25t-4.75-11.25 t-11.25-4.75l-112.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,112.00 q0.00,6.50 4.75,11.25t 11.25,4.75t 11.25-4.75l 36.00-36.00l 83.00,83.00q 2.50,2.50 5.75,2.50t 5.75-2.50l 28.50-28.50q 2.50-2.50 2.50-5.75z" horiz-adv-x="384" />
+<glyph unicode="&#xf071;" d="M 256.00,40.25l0.00,47.50 q0.00,3.50 -2.375,5.875t-5.625,2.375l-48.00,0.00 q-3.25,0.00 -5.625-2.375t-2.375-5.875l0.00-47.50 q0.00-3.50 2.375-5.875t 5.625-2.375l 48.00,0.00 q 3.25,0.00 5.625,2.375t 2.375,5.875zM 255.50,133.75l 4.50,114.75q0.00,3.00 -2.50,4.75q-3.25,2.75 -6.00,2.75l-55.00,0.00 q-2.75,0.00 -6.00-2.75q-2.50-1.75 -2.50-5.25l 4.25-114.25q0.00-2.50 2.50-4.125t 6.00-1.625l 46.25,0.00 q 3.50,0.00 5.875,1.625t 2.625,4.125zM 252.00,367.25l 192.00-352.00q 8.75-15.75 -0.50-31.50q-4.25-7.25 -11.625-11.50t-15.875-4.25l-384.00,0.00 q-8.50,0.00 -15.875,4.25t-11.625,11.50q-9.25,15.75 -0.50,31.50l 192.00,352.00q 4.25,7.75 11.75,12.25t 16.25,4.50t 16.25-4.50t 11.75-12.25z" />
+<glyph unicode="&#xf05a;" d="M 256.00,40.00l0.00,16.00 q0.00,3.50 -2.25,5.75t-5.75,2.25l-24.00,0.00 l0.00,120.00 q0.00,3.50 -2.25,5.75t-5.75,2.25l-80.00,0.00 q-3.50,0.00 -5.75-2.25t-2.25-5.75l0.00-16.00 q0.00-3.50 2.25-5.75t 5.75-2.25l 24.00,0.00 l0.00-96.00 l-24.00,0.00 q-3.50,0.00 -5.75-2.25t-2.25-5.75l0.00-16.00 q0.00-3.50 2.25-5.75t 5.75-2.25l 112.00,0.00 q 3.50,0.00 5.75,2.25t 2.25,5.75zM 224.00,232.00l0.00,48.00 q0.00,3.50 -2.25,5.75t-5.75,2.25l-48.00,0.00 q-3.50,0.00 -5.75-2.25t-2.25-5.75l0.00-48.00 q0.00-3.50 2.25-5.75 t 5.75-2.25l 48.00,0.00 q 3.50,0.00 5.75,2.25t 2.25,5.75zM 384.00,160.00q0.00-52.25 -25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" />
+<glyph unicode="&#xf06a;" d="M 192.00,352.00q 52.25,0.00 96.375-25.75t 69.875-69.875t 25.75-96.375t-25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75zM 224.00,40.25l0.00,47.50 q0.00,3.50 -2.25,5.875t-5.50,2.375l-48.00,0.00 q-3.25,0.00 -5.75-2.50t-2.50-5.75l0.00-47.50 q0.00-3.25 2.50-5.75t 5.75-2.50l 48.00,0.00 q 3.25,0.00 5.50,2.375t 2.25,5.875zM 223.50,126.25l 4.50,155.25q0.00,3.00 -2.50,4.50q-2.50,2.00 -6.00,2.00l-55.00,0.00 q-3.50,0.00 -6.00-2.00q-2.50-1.50 -2.50-4.50l 4.25-155.25q0.00-2.50 2.50-4.375t 6.00-1.875l 46.25,0.00 q 3.50,0.00 5.875,1.875t 2.625,4.375z" horiz-adv-x="384" />
+<glyph unicode="&#xf05b;" d="M 299.25,128.00l-27.25,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 27.25,0.00 q-8.00,27.00 -28.125,47.125t-47.125,28.125l0.00-27.25 q0.00-6.50 -4.75-11.25t-11.25-4.75l-32.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,27.25 q-27.00-8.00 -47.125-28.125t-28.125-47.125l 27.25,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-27.25,0.00 q 8.00-27.00 28.125-47.125t 47.125-28.125l0.00,27.25 q0.00,6.50 4.75,11.25t 11.25,4.75l 32.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25l0.00-27.25 q 27.00,8.00 47.125,28.125t 28.125,47.125zM 384.00,176.00l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-35.75,0.00 q-9.25-40.25 -38.625-69.625t-69.625-38.625l0.00-35.75 q0.00-6.50 -4.75-11.25t-11.25-4.75l-32.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,35.75 q-40.25,9.25 -69.625,38.625t-38.625,69.625l-35.75,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 35.75,0.00 q 9.25,40.25 38.625,69.625t 69.625,38.625l0.00,35.75 q0.00,6.50 4.75,11.25t 11.25,4.75l 32.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25l0.00-35.75 q 40.25-9.25 69.625-38.625t 38.625-69.625l 35.75,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" />
+<glyph unicode="&#xf0c9;" d="M 384.00,48.00l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-352.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 352.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 384.00,176.00l0.00-32.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-352.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 352.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 384.00,304.00l0.00-32.00 q0.00-6.50 -4.75-11.25 t-11.25-4.75l-352.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,32.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 352.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" />
+<glyph unicode="&#xf0d0;" d="M 297.50,238.75l 73.25,73.25l-26.75,26.75l-73.25-73.25zM 409.25,312.00q0.00-6.75 -4.50-11.25l-321.50-321.50q-4.50-4.50 -11.25-4.50t-11.25,4.50l-49.50,49.50q-4.50,4.50 -4.50,11.25t 4.50,11.25l 321.50,321.50q 4.50,4.50 11.25,4.50t 11.25-4.50l 49.50-49.50q 4.50-4.50 4.50-11.25zM 71.50,359.50l 24.50-7.50l-24.50-7.50l-7.50-24.50l-7.50,24.50l-24.50,7.50l 24.50,7.50l 7.50,24.50zM 159.00,319.00 l 49.00-15.00l-49.00-15.00l-15.00-49.00l-15.00,49.00l-49.00,15.00l 49.00,15.00l 15.00,49.00zM 391.50,199.50l 24.50-7.50l-24.50-7.50l-7.50-24.50l-7.50,24.50l-24.50,7.50l 24.50,7.50l 7.50,24.50zM 231.50,359.50l 24.50-7.50l-24.50-7.50l-7.50-24.50l-7.50,24.50l-24.50,7.50l 24.50,7.50l 7.50,24.50z" horiz-adv-x="416" />
+<glyph unicode="&#xf0e8;" d="M 448.00,72.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-80.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 24.00,0.00 l0.00,48.00 l-128.00,0.00 l0.00-48.00 l 24.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-80.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 24.00,0.00 l0.00,48.00 l-128.00,0.00 l0.00-48.00 l 24.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-80.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 24.00,0.00 l0.00,48.00 q0.00,13.00 9.50,22.50t 22.50,9.50l 128.00,0.00 l0.00,48.00 l-24.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,80.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 80.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00l0.00-80.00 q0.00-10.00 -7.00-17.00t-17.00-7.00l-24.00,0.00 l0.00-48.00 l 128.00,0.00 q 13.00,0.00 22.50-9.50t 9.50-22.50l0.00-48.00 l 24.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00 z" />
+<glyph unicode="&#xf013;" d="M 256.00,160.00q0.00,26.50 -18.75,45.25t-45.25,18.75t-45.25-18.75t-18.75-45.25t 18.75-45.25t 45.25-18.75t 45.25,18.75t 18.75,45.25zM 384.00,187.25l0.00-55.50 q0.00-3.00 -2.00-5.75t-5.00-3.25l-46.25-7.00q-4.75-13.50 -9.75-22.75q 8.75-12.50 26.75-34.50q 2.50-3.00 2.50-6.25t-2.25-5.75q-6.75-9.25 -24.75-27.00t-23.50-17.75q-3.00,0.00 -6.50,2.25l-34.50,27.00q-11.00-5.75 -22.75-9.50 q-4.00-34.00 -7.25-46.50q-1.75-7.00 -9.00-7.00l-55.50,0.00 q-3.50,0.00 -6.125,2.125t-2.875,5.375l-7.00,46.00q-12.25,4.00 -22.50,9.25l-35.25-26.75q-2.50-2.25 -6.25-2.25q-3.50,0.00 -6.25,2.75q-31.50,28.50 -41.25,42.00q-1.75,2.50 -1.75,5.75q0.00,3.00 2.00,5.75q 3.75,5.25 12.75,16.625t 13.50,17.625q-6.75,12.50 -10.25,24.75l-45.75,6.75q-3.25,0.50 -5.25,3.125t-2.00,5.875l0.00,55.50 q0.00,3.00 2.00,5.75t 4.75,3.25 l 46.50,7.00q 3.50,11.50 9.75,23.00q-10.00,14.25 -26.75,34.50q-2.50,3.00 -2.50,6.00q0.00,2.50 2.25,5.75q 6.50,9.00 24.625,26.875t 23.625,17.875q 3.25,0.00 6.50-2.50l 34.50-26.75q 11.00,5.75 22.75,9.50q 4.00,34.00 7.25,46.50q 1.75,7.00 9.00,7.00l 55.50,0.00 q 3.50,0.00 6.125-2.125t 2.875-5.375l 7.00-46.00q 12.25-4.00 22.50-9.25l 35.50,26.75q 2.25,2.25 6.00,2.25q 3.25,0.00 6.25-2.50q 32.25-29.75 41.25-42.50q 1.75-2.00 1.75-5.50 q0.00-3.00 -2.00-5.75q-3.75-5.25 -12.75-16.625t-13.50-17.625q 6.50-12.50 10.25-24.50l 45.75-7.00q 3.25-0.50 5.25-3.125t 2.00-5.875z" horiz-adv-x="384" />
+<glyph unicode="&#xf0ec;" d="M 448.00,88.00l0.00-48.00 q0.00-3.25 -2.375-5.625t-5.625-2.375l-344.00,0.00 l0.00-48.00 q0.00-3.25 -2.375-5.625t-5.625-2.375q-3.00,0.00 -6.00,2.50l-79.75,80.00q-2.25,2.25 -2.25,5.50q0.00,3.50 2.25,5.75l 80.00,80.00q 2.25,2.25 5.75,2.25q 3.25,0.00 5.625-2.375t 2.375-5.625l0.00-48.00 l 344.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625zM 448.00,224.00q0.00-3.50 -2.25-5.75l-80.00-80.00q-2.25-2.25 -5.75-2.25 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,48.00 l-344.00,0.00 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,48.00 q0.00,3.25 2.375,5.625t 5.625,2.375l 344.00,0.00 l0.00,48.00 q0.00,3.50 2.25,5.75t 5.75,2.25q 3.00,0.00 6.00-2.50l 79.75-79.75q 2.25-2.25 2.25-5.75z" />
+<glyph unicode="&#xf0f0;" d="M 96.00,48.00q0.00-6.50 -4.75-11.25t-11.25-4.75t-11.25,4.75t-4.75,11.25t 4.75,11.25t 11.25,4.75t 11.25-4.75t 4.75-11.25zM 352.00,32.75q0.00-30.25 -18.25-47.50t-48.50-17.25l-218.50,0.00 q-30.25,0.00 -48.50,17.25t-18.25,47.50q0.00,17.00 1.375,32.75t 6.00,34.50t 11.875,33.125t 20.25,25.75t 30.00,15.125q-5.50-13.00 -5.50-30.00l0.00-50.75 q-14.50-5.00 -23.25-17.50t-8.75-27.75q0.00-20.00 14.00-34.00t 34.00-14.00 t 34.00,14.00t 14.00,34.00q0.00,15.25 -8.875,27.75t-23.125,17.50l0.00,50.75 q0.00,15.50 6.25,23.25q 33.00-26.00 73.75-26.00t 73.75,26.00q 6.25-7.75 6.25-23.25l0.00-16.00 q-26.50,0.00 -45.25-18.75t-18.75-45.25l0.00-22.25 q-8.00-7.25 -8.00-17.75q0.00-10.00 7.00-17.00t 17.00-7.00t 17.00,7.00t 7.00,17.00q0.00,10.50 -8.00,17.75l0.00,22.25 q0.00,13.00 9.50,22.50t 22.50,9.50t 22.50-9.50t 9.50-22.50l0.00-22.25 q-8.00-7.25 -8.00-17.75q0.00-10.00 7.00-17.00 t 17.00-7.00t 17.00,7.00t 7.00,17.00q0.00,10.50 -8.00,17.75l0.00,22.25 q0.00,17.00 -8.625,31.875t-23.375,23.375q0.00,2.50 0.125,10.625t0.00,12.00t-0.625,10.375t-1.75,11.75t-3.25,10.00q 17.00-3.75 30.00-15.125t 20.25-25.75t 11.875-33.125t 6.00-34.50t 1.375-32.75zM 272.00,256.00q0.00-39.75 -28.125-67.875t-67.875-28.125t-67.875,28.125t-28.125,67.875t 28.125,67.875t 67.875,28.125 t 67.875-28.125t 28.125-67.875z" horiz-adv-x="352" />
+<glyph unicode="&#xf023;" d="M 176.00,128.00q0.00,13.25 -9.375,22.625t-22.625,9.375t-22.625-9.375t-9.375-22.625q0.00-9.25 4.75-16.75t 12.75-11.75l-17.25-57.25q-1.25-3.75 1.25-7.00t 6.50-3.25l 48.00,0.00 q 4.00,0.00 6.50,3.25t 1.25,7.00l-17.25,57.25q 8.00,4.25 12.75,11.75t 4.75,16.75zM 80.00,192.00l 128.00,0.00 l0.00,48.00 q0.00,26.50 -18.75,45.25t-45.25,18.75t-45.25-18.75t-18.75-45.25l0.00-48.00 zM 288.00,168.00l0.00-144.00 q0.00-10.00 -7.00-17.00 t-17.00-7.00l-240.00,0.00 q-10.00,0.00 -17.00,7.00t-7.00,17.00l0.00,144.00 q0.00,10.00 7.00,17.00t 17.00,7.00l 8.00,0.00 l0.00,48.00 q0.00,46.00 33.00,79.00t 79.00,33.00t 79.00-33.00t 33.00-79.00l0.00-48.00 l 8.00,0.00 q 10.00,0.00 17.00-7.00t 7.00-17.00z" horiz-adv-x="288" />
+<glyph unicode="&#xf10c;" d="M 320.00,160.00q0.00,26.00 -10.125,49.625t-27.375,40.875t-40.875,27.375t-49.625,10.125t-49.625-10.125t-40.875-27.375t-27.375-40.875t-10.125-49.625t 10.125-49.625t 27.375-40.875t 40.875-27.375t 49.625-10.125t 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625zM 384.00,160.00q0.00-52.25 -25.75-96.375 t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" />
+<glyph unicode="&#xf111;" d="M 384.00,160.00q0.00-52.25 -25.75-96.375t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" />
+<glyph unicode="&#xf110;" d="M 124.00,48.00q0.00-15.00 -10.625-25.50t-25.375-10.50q-15.00,0.00 -25.50,10.50t-10.50,25.50t 10.50,25.50t 25.50,10.50q 14.75,0.00 25.375-10.50t 10.625-25.50zM 232.00,0.00q0.00-13.25 -9.375-22.625t-22.625-9.375t-22.625,9.375t-9.375,22.625t 9.375,22.625t 22.625,9.375t 22.625-9.375t 9.375-22.625zM 80.00,160.00q0.00-16.50 -11.75-28.25t-28.25-11.75t-28.25,11.75t-11.75,28.25 t 11.75,28.25t 28.25,11.75t 28.25-11.75t 11.75-28.25zM 340.00,48.00q0.00-11.50 -8.25-19.75t-19.75-8.25t-19.75,8.25t-8.25,19.75t 8.25,19.75t 19.75,8.25t 19.75-8.25t 8.25-19.75zM 132.00,272.00q0.00-18.25 -12.875-31.125t-31.125-12.875t-31.125,12.875t-12.875,31.125t 12.875,31.125t 31.125,12.875t 31.125-12.875t 12.875-31.125zM 248.00,320.00q0.00-20.00 -14.00-34.00t-34.00-14.00 t-34.00,14.00t-14.00,34.00t 14.00,34.00t 34.00,14.00t 34.00-14.00t 14.00-34.00zM 384.00,160.00q0.00-10.00 -7.00-17.00t-17.00-7.00t-17.00,7.00t-7.00,17.00t 7.00,17.00t 17.00,7.00t 17.00-7.00t 7.00-17.00zM 332.00,272.00q0.00-8.25 -5.875-14.125t-14.125-5.875t-14.125,5.875t-5.875,14.125t 5.875,14.125t 14.125,5.875t 14.125-5.875t 5.875-14.125z" horiz-adv-x="392" />
+<glyph unicode="&#xf05e;" d="M 320.00,160.00q0.00,34.75 -17.75,65.00l-175.25-175.25q 30.25-17.75 65.00-17.75q 26.00,0.00 49.625,10.125t 40.875,27.375t 27.375,40.875t 10.125,49.625zM 81.75,95.00l 175.25,175.25q-30.25,17.75 -65.00,17.75q-26.00,0.00 -49.625-10.125t-40.875-27.375t-27.375-40.875t-10.125-49.625q0.00-34.75 17.75-65.00zM 384.00,160.00q0.00-52.25 -25.75-96.375 t-69.875-69.875t-96.375-25.75t-96.375,25.75t-69.875,69.875t-25.75,96.375t 25.75,96.375t 69.875,69.875t 96.375,25.75t 96.375-25.75t 69.875-69.875t 25.75-96.375z" horiz-adv-x="384" />
+<glyph unicode="&#xf065;" d="M 188.75,120.00q0.00-3.25 -2.50-5.75l-83.00-83.00l 36.00-36.00q 4.75-4.75 4.75-11.25t-4.75-11.25t-11.25-4.75l-112.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,112.00 q0.00,6.50 4.75,11.25t 11.25,4.75t 11.25-4.75l 36.00-36.00l 83.00,83.00q 2.50,2.50 5.75,2.50t 5.75-2.50l 28.50-28.50q 2.50-2.50 2.50-5.75zM 384.00,336.00l0.00-112.00 q0.00-6.50 -4.75-11.25t-11.25-4.75t-11.25,4.75l-36.00,36.00l-83.00-83.00 q-2.50-2.50 -5.75-2.50t-5.75,2.50l-28.50,28.50q-2.50,2.50 -2.50,5.75t 2.50,5.75l 83.00,83.00l-36.00,36.00q-4.75,4.75 -4.75,11.25t 4.75,11.25t 11.25,4.75l 112.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" />
+<glyph unicode="&#xf021;" d="M 377.75,120.00q0.00-1.25 -0.25-1.75q-16.00-67.00 -67.00-108.625t-119.50-41.625q-36.50,0.00 -70.625,13.75t-60.875,39.25l-32.25-32.25q-4.75-4.75 -11.25-4.75t-11.25,4.75t-4.75,11.25l0.00,112.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 112.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25t-4.75-11.25l-34.25-34.25q 17.75-16.50 40.25-25.50t 46.75-9.00q 33.50,0.00 62.50,16.25t 46.50,44.75q 2.75,4.25 13.25,29.25 q 2.00,5.75 7.50,5.75l 48.00,0.00 q 3.25,0.00 5.625-2.375t 2.375-5.625zM 384.00,320.00l0.00-112.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-112.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25t 4.75,11.25l 34.50,34.50q-37.00,34.25 -87.25,34.25q-33.50,0.00 -62.50-16.25t-46.50-44.75q-2.75-4.25 -13.25-29.25q-2.00-5.75 -7.50-5.75l-49.75,0.00 q-3.25,0.00 -5.625,2.375t-2.375,5.625l0.00,1.75 q 16.25,67.00 67.50,108.625t 120.00,41.625 q 36.50,0.00 71.00-13.875t 61.25-39.125l 32.50,32.25q 4.75,4.75 11.25,4.75t 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" />
+<glyph unicode="&#xf02e;" d="M 291.00,352.00q 5.75,0.00 11.00-2.25q 8.25-3.25 13.125-10.25t 4.875-15.50l0.00-322.25 q0.00-8.50 -4.875-15.50t-13.125-10.25q-4.75-2.00 -11.00-2.00q-12.00,0.00 -20.75,8.00l-110.25,106.00l-110.25-106.00q-9.00-8.25 -20.75-8.25q-5.75,0.00 -11.00,2.25q-8.25,3.25 -13.125,10.25t-4.875,15.50l0.00,322.25 q0.00,8.50 4.875,15.50t 13.125,10.25q 5.25,2.25 11.00,2.25l 262.00,0.00 z" horiz-adv-x="320" />
+<glyph unicode="&#x20;" horiz-adv-x="224" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,384L 448 -64L0 -64 z" horiz-adv-x="0" />
+</font></defs></svg> \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/base/debug/fonts/font.ttf b/WebContent/VAADIN/themes/base/debug/fonts/font.ttf
new file mode 100644
index 0000000000..e26c910020
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/debug/fonts/font.ttf
Binary files differ
diff --git a/WebContent/VAADIN/themes/base/debug/fonts/font.woff b/WebContent/VAADIN/themes/base/debug/fonts/font.woff
new file mode 100644
index 0000000000..e23e3807d0
--- /dev/null
+++ b/WebContent/VAADIN/themes/base/debug/fonts/font.woff
Binary files differ
diff --git a/client/src/com/vaadin/Vaadin.gwt.xml b/client/src/com/vaadin/Vaadin.gwt.xml
index dcc5b0d294..11197bffc5 100644
--- a/client/src/com/vaadin/Vaadin.gwt.xml
+++ b/client/src/com/vaadin/Vaadin.gwt.xml
@@ -24,7 +24,7 @@
<when-type-is class="com.google.gwt.core.client.impl.SchedulerImpl" />
</replace-with>
- <replace-with class="com.vaadin.client.VDebugConsole">
+ <replace-with class="com.vaadin.client.debug.internal.ConsoleAdapter">
<when-type-is class="com.vaadin.client.Console" />
</replace-with>
diff --git a/client/src/com/vaadin/client/VDebugConsole.java b/client/src/com/vaadin/client/VDebugConsole.java
index ee7505876d..025bbb2678 100644
--- a/client/src/com/vaadin/client/VDebugConsole.java
+++ b/client/src/com/vaadin/client/VDebugConsole.java
@@ -566,7 +566,7 @@ public class VDebugConsole extends VOverlay implements Console {
JsArray<ValueMap> valueMapArray = meta
.getJSValueMapArray("invalidLayouts");
int size = valueMapArray.length();
- panel.add(new HTML("<div>************************</di>"
+ panel.add(new HTML("<div>************************</div>"
+ "<h4>Layouts analyzed on server, total top level problems: "
+ size + " </h4>"));
if (size > 0) {
@@ -586,12 +586,12 @@ public class VDebugConsole extends VOverlay implements Console {
+ "states, but reported here as they might be.</em>"));
if (zeroHeightComponents.size() > 0) {
panel.add(new HTML(
- "<p><strong>Vertically zero size:</strong><p>"));
+ "<p><strong>Vertically zero size:</strong></p>"));
printClientSideDetectedIssues(zeroHeightComponents, ac);
}
if (zeroWidthComponents.size() > 0) {
panel.add(new HTML(
- "<p><strong>Horizontally zero size:</strong><p>"));
+ "<p><strong>Horizontally zero size:</strong></p>"));
printClientSideDetectedIssues(zeroWidthComponents, ac);
}
}
diff --git a/client/src/com/vaadin/client/ValueMap.java b/client/src/com/vaadin/client/ValueMap.java
index 5157bc91f5..4141eaa9d6 100644
--- a/client/src/com/vaadin/client/ValueMap.java
+++ b/client/src/com/vaadin/client/ValueMap.java
@@ -70,12 +70,12 @@ public final class ValueMap extends JavaScriptObject {
return attrs;
}
- native JsArrayString getJSStringArray(String name)
+ public native JsArrayString getJSStringArray(String name)
/*-{
return this[name];
}-*/;
- native JsArray<ValueMap> getJSValueMapArray(String name)
+ public native JsArray<ValueMap> getJSValueMapArray(String name)
/*-{
return this[name];
}-*/;
diff --git a/client/src/com/vaadin/client/debug/internal/ConsoleAdapter.java b/client/src/com/vaadin/client/debug/internal/ConsoleAdapter.java
new file mode 100644
index 0000000000..13ec8a43ff
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/ConsoleAdapter.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import java.util.Set;
+
+import com.google.gwt.core.shared.GWT;
+import com.google.gwt.event.shared.UmbrellaException;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConfiguration;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ComponentConnector;
+import com.vaadin.client.Console;
+import com.vaadin.client.Util;
+import com.vaadin.client.ValueMap;
+import com.vaadin.client.ui.VNotification;
+
+/**
+ * Internal API, do not use. Implements the 'old' Console API and passes the
+ * messages to the new debug window.
+ * <p>
+ * <em>WILL BE CHANGED/REMOVED.</em>
+ * </p>
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class ConsoleAdapter implements Console {
+
+ static VDebugWindow window = GWT.create(VDebugWindow.class);
+
+ static {
+ window.addSection((Section) GWT.create(LogSection.class));
+ window.addSection((Section) GWT.create(HierarchySection.class));
+ window.addSection((Section) GWT.create(NetworkSection.class));
+
+ }
+
+ @Override
+ public void log(String msg) {
+ window.log(Level.LOG, msg);
+
+ GWT.log(msg);
+ consoleLog(msg);
+ System.out.println(msg);
+ }
+
+ @Override
+ public void log(Throwable e) {
+ if (e instanceof UmbrellaException) {
+ UmbrellaException ue = (UmbrellaException) e;
+ for (Throwable t : ue.getCauses()) {
+ log(t);
+ }
+ return;
+ }
+ log(Util.getSimpleName(e) + ": " + e.getMessage());
+ GWT.log(e.getMessage(), e);
+ }
+
+ @Override
+ public void error(Throwable e) {
+ handleError(e, this);
+ }
+
+ @Override
+ public void error(String msg) {
+ if (msg == null) {
+ msg = "null";
+ }
+ window.log(Level.ERROR, msg);
+
+ GWT.log(msg);
+ consoleErr(msg);
+ System.out.println(msg);
+ }
+
+ @Override
+ public void printObject(Object msg) {
+ String str;
+ if (msg == null) {
+ str = "null";
+ } else {
+ str = msg.toString();
+ }
+ log(str);
+ consoleLog(str);
+ }
+
+ @Override
+ public void dirUIDL(ValueMap u, ApplicationConnection client) {
+ window.uidl(client, u);
+ }
+
+ @Override
+ public void printLayoutProblems(ValueMap meta,
+ ApplicationConnection applicationConnection,
+ Set<ComponentConnector> zeroHeightComponents,
+ Set<ComponentConnector> zeroWidthComponents) {
+
+ window.meta(applicationConnection, meta);
+ }
+
+ @Override
+ public void setQuietMode(boolean quietDebugMode) {
+ if (quietDebugMode) {
+ window.close();
+ }
+ }
+
+ @Override
+ public void init() {
+ window.init();
+ }
+
+ static void handleError(Throwable e, Console target) {
+ if (e instanceof UmbrellaException) {
+ UmbrellaException ue = (UmbrellaException) e;
+ for (Throwable t : ue.getCauses()) {
+ target.error(t);
+ }
+ return;
+ }
+ String exceptionText = Util.getSimpleName(e);
+ String message = e.getMessage();
+ if (message != null && message.length() != 0) {
+ exceptionText += ": " + e.getMessage();
+ }
+ target.error(exceptionText);
+ GWT.log(e.getMessage(), e);
+ if (!GWT.isProdMode()) {
+ e.printStackTrace();
+ }
+ try {
+ Widget owner = null;
+
+ if (!ApplicationConfiguration.getRunningApplications().isEmpty()) {
+ // Make a wild guess and use the first available
+ // ApplicationConnection. This is better than than leaving the
+ // exception completely unstyled...
+ ApplicationConnection connection = ApplicationConfiguration
+ .getRunningApplications().get(0);
+ owner = connection.getUIConnector().getWidget();
+ }
+ VNotification
+ .createNotification(VNotification.DELAY_FOREVER, owner)
+ .show("<h1>Uncaught client side exception</h1><br />"
+ + exceptionText, VNotification.CENTERED, "error");
+ } catch (Exception e2) {
+ // Just swallow this exception
+ }
+ }
+
+ private static native void consoleLog(String msg)
+ /*-{
+ if($wnd.console && $wnd.console.log) {
+ $wnd.console.log(msg);
+ }
+ }-*/;
+
+ private static native void consoleErr(String msg)
+ /*-{
+ if($wnd.console) {
+ if ($wnd.console.error)
+ $wnd.console.error(msg);
+ else if ($wnd.console.log)
+ $wnd.console.log(msg);
+ }
+ }-*/;
+}
diff --git a/client/src/com/vaadin/client/debug/internal/DebugButton.java b/client/src/com/vaadin/client/debug/internal/DebugButton.java
new file mode 100644
index 0000000000..a49a392fbe
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/DebugButton.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import com.google.gwt.user.client.ui.Button;
+
+/**
+ * Simple extension of {@link Button} that is preconfigured with for use in
+ * {@link VDebugWindow}. Uses icon-font for icons, and allows title to be
+ * specified in the constructor.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class DebugButton extends Button {
+
+ protected boolean active = false;
+
+ /**
+ * Creates a {@link Button} with the given icon-font icon. The icon id will
+ * be used in the <i>data-icon</i> attribute of an <i>&lt;i&gt;</i> -tag.
+ *
+ * @param icon
+ * Identifier for the desired icon in an icon-font
+ */
+ public DebugButton(Icon icon) {
+ this(icon, null, null);
+ }
+
+ /*-
+ public DebugButton(String caption) {
+ this(null, null, caption);
+ }
+
+ public DebugButton(String caption, String title) {
+ this(null, title, caption);
+ }
+ -*/
+
+ /**
+ * Creates a {@link Button} with the given icon-font icon and title
+ * (tooltip). The icon id will be used in the <i>data-icon</i> attribute of
+ * an <i>&lt;i&gt;</i> -tag.
+ *
+ * @param icon
+ * Identifier for the desired icon in an icon-font
+ * @param title
+ * Button title (tooltip)
+ *
+ */
+ public DebugButton(Icon icon, String title) {
+ this(icon, title, null);
+ }
+
+ /**
+ * Creates a {@link Button} with the given icon-font icon, title (tooltip),
+ * and caption. The icon id will be used in the <i>data-icon</i> attribute
+ * of an <i>&lt;i&gt;</i> -tag.
+ *
+ * @param icon
+ * Identifier for the desired icon in an icon-font
+ * @param title
+ * Title (tooltip)
+ * @param caption
+ * Button baption
+ */
+ public DebugButton(Icon icon, String title, String caption) {
+ super((icon != null ? icon : "") + (caption != null ? caption : ""));
+ if (title != null) {
+ setTitle(title);
+ }
+
+ setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON);
+ }
+
+ /**
+ * Adds or removes a stylename, indicating whether or not the button is in
+ * it's active state.
+ *
+ * @param active
+ */
+ public void setActive(boolean active) {
+ this.active = active;
+ setStyleDependentName(VDebugWindow.STYLENAME_ACTIVE, active);
+ }
+
+ /**
+ * Indicates wheter the Button is currently in its active state or not
+ *
+ * @return true if the Button is active, false otherwise
+ */
+ public boolean isActive() {
+ return active;
+ }
+
+}
diff --git a/client/src/com/vaadin/client/debug/internal/HierarchySection.java b/client/src/com/vaadin/client/debug/internal/HierarchySection.java
new file mode 100644
index 0000000000..d353cf661a
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/HierarchySection.java
@@ -0,0 +1,574 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.google.gwt.core.client.JsArray;
+import com.google.gwt.dom.client.Style.TextDecoration;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConfiguration;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ComponentConnector;
+import com.vaadin.client.ComputedStyle;
+import com.vaadin.client.ConnectorMap;
+import com.vaadin.client.ServerConnector;
+import com.vaadin.client.SimpleTree;
+import com.vaadin.client.Util;
+import com.vaadin.client.VConsole;
+import com.vaadin.client.ValueMap;
+import com.vaadin.client.ui.UnknownComponentConnector;
+import com.vaadin.shared.AbstractComponentState;
+
+/**
+ * Provides functionality for examining the UI component hierarchy.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+class HierarchySection implements Section {
+
+ private final DebugButton tabButton = new DebugButton(Icon.HIERARCHY,
+ "Examine compoent hierarchy");
+
+ private final FlowPanel content = new FlowPanel();
+ private final FlowPanel controls = new FlowPanel();
+
+ private final Button find = new DebugButton(Icon.HIGHLIGHT,
+ "Select a component on the page to inspect it");
+ private final Button analyze = new DebugButton(Icon.ANALYZE,
+ "Check layouts for potential problems");
+ private final Button generateWS = new DebugButton(Icon.OPTIMIZE,
+ "Show used connectors and how to optimized widgetset");
+
+ private HandlerRegistration highlightModeRegistration = null;
+
+ public HierarchySection() {
+ controls.add(find);
+ find.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON);
+ find.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ toggleFind();
+ }
+ });
+
+ controls.add(analyze);
+ analyze.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON);
+ analyze.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ stopFind();
+ analyzeLayouts();
+ }
+ });
+
+ controls.add(generateWS);
+ generateWS.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON);
+ generateWS.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ generateWidgetset();
+ }
+ });
+
+ content.setStylePrimaryName(VDebugWindow.STYLENAME + "-hierarchy");
+ }
+
+ @Override
+ public DebugButton getTabButton() {
+ return tabButton;
+ }
+
+ @Override
+ public Widget getControls() {
+ return controls;
+ }
+
+ @Override
+ public Widget getContent() {
+ return content;
+ }
+
+ @Override
+ public void show() {
+
+ }
+
+ @Override
+ public void hide() {
+ stopFind();
+ }
+
+ @Override
+ public void log(Level level, String msg) {
+ // TODO
+ }
+
+ private void generateWidgetset() {
+
+ content.clear();
+ HTML h = new HTML("Getting used connectors");
+ content.add(h);
+
+ String s = "";
+ for (ApplicationConnection ac : ApplicationConfiguration
+ .getRunningApplications()) {
+ ApplicationConfiguration conf = ac.getConfiguration();
+ s += "<h1>Used connectors for " + conf.getServiceUrl() + "</h1>";
+
+ for (String connectorName : getUsedConnectorNames(conf)) {
+ s += connectorName + "<br/>";
+ }
+
+ s += "<h2>To make an optimized widgetset based on these connectors, do:</h2>";
+ s += "<h3>1. Add to your widgetset.gwt.xml file:</h2>";
+ s += "<textarea rows=\"3\" style=\"width:90%\">";
+ s += "<generate-with class=\"OptimizedConnectorBundleLoaderFactory\">\n";
+ s += " <when-type-assignable class=\"com.vaadin.client.metadata.ConnectorBundleLoader\" />\n";
+ s += "</generate-with>";
+ s += "</textarea>";
+
+ s += "<h3>2. Add the following java file to your project:</h2>";
+ s += "<textarea rows=\"5\" style=\"width:90%\">";
+ s += generateOptimizedWidgetSet(getUsedConnectorNames(conf));
+ s += "</textarea>";
+ s += "<h3>3. Recompile widgetset</h2>";
+
+ }
+
+ h.setHTML(s);
+ }
+
+ private Set<String> getUsedConnectorNames(
+ ApplicationConfiguration configuration) {
+ int tag = 0;
+ Set<String> usedConnectors = new HashSet<String>();
+ while (true) {
+ String serverSideClass = configuration
+ .getServerSideClassNameForTag(tag);
+ if (serverSideClass == null) {
+ break;
+ }
+ Class<? extends ServerConnector> connectorClass = configuration
+ .getConnectorClassByEncodedTag(tag);
+ if (connectorClass == null) {
+ break;
+ }
+
+ if (connectorClass != UnknownComponentConnector.class) {
+ usedConnectors.add(connectorClass.getName());
+ }
+ tag++;
+ if (tag > 10000) {
+ // Sanity check
+ VConsole.error("Search for used connector classes was forcefully terminated");
+ break;
+ }
+ }
+ return usedConnectors;
+ }
+
+ public String generateOptimizedWidgetSet(Set<String> usedConnectors) {
+ String s = "import java.util.HashSet;\n";
+ s += "import java.util.Set;\n";
+
+ s += "import com.google.gwt.core.ext.typeinfo.JClassType;\n";
+ s += "import com.vaadin.client.ui.ui.UIConnector;\n";
+ s += "import com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory;\n";
+ s += "import com.vaadin.shared.ui.Connect.LoadStyle;\n\n";
+
+ s += "public class OptimizedConnectorBundleLoaderFactory extends\n";
+ s += " ConnectorBundleLoaderFactory {\n";
+ s += " private Set<String> eagerConnectors = new HashSet<String>();\n";
+ s += " {\n";
+ for (String c : usedConnectors) {
+ s += " eagerConnectors.add(" + c
+ + ".class.getName());\n";
+ }
+ s += " }\n";
+ s += "\n";
+ s += " @Override\n";
+ s += " protected LoadStyle getLoadStyle(JClassType connectorType) {\n";
+ s += " if (eagerConnectors.contains(connectorType.getQualifiedBinaryName())) {\n";
+ s += " return LoadStyle.EAGER;\n";
+ s += " } else {\n";
+ s += " // Loads all other connectors immediately after the initial view has\n";
+ s += " // been rendered\n";
+ s += " return LoadStyle.DEFERRED;\n";
+ s += " }\n";
+ s += " }\n";
+ s += "}\n";
+
+ return s;
+ }
+
+ private void analyzeLayouts() {
+ content.clear();
+ content.add(new Label("Analyzing layouts..."));
+ List<ApplicationConnection> runningApplications = ApplicationConfiguration
+ .getRunningApplications();
+ for (ApplicationConnection applicationConnection : runningApplications) {
+ applicationConnection.analyzeLayouts();
+ }
+ }
+
+ public void meta(ApplicationConnection ac, ValueMap meta) {
+ content.clear();
+ JsArray<ValueMap> valueMapArray = meta
+ .getJSValueMapArray("invalidLayouts");
+ int size = valueMapArray.length();
+
+ if (size > 0) {
+ SimpleTree root = new SimpleTree("Layouts analyzed, " + size
+ + " top level problems");
+ for (int i = 0; i < size; i++) {
+ printLayoutError(ac, valueMapArray.get(i), root);
+ }
+ root.open(false);
+ content.add(root);
+ } else {
+ content.add(new Label("Layouts analyzed, no top level problems"));
+ }
+
+ Set<ComponentConnector> zeroHeightComponents = new HashSet<ComponentConnector>();
+ Set<ComponentConnector> zeroWidthComponents = new HashSet<ComponentConnector>();
+ findZeroSizeComponents(zeroHeightComponents, zeroWidthComponents,
+ ac.getUIConnector());
+ if (zeroHeightComponents.size() > 0 || zeroWidthComponents.size() > 0) {
+ content.add(new HTML("<h4> Client side notifications</h4>"
+ + " <em>The following relative sized components were "
+ + "rendered to a zero size container on the client side."
+ + " Note that these are not necessarily invalid "
+ + "states, but reported here as they might be.</em>"));
+ if (zeroHeightComponents.size() > 0) {
+ content.add(new HTML(
+ "<p><strong>Vertically zero size:</strong></p>"));
+ printClientSideDetectedIssues(zeroHeightComponents, ac);
+ }
+ if (zeroWidthComponents.size() > 0) {
+ content.add(new HTML(
+ "<p><strong>Horizontally zero size:</strong></p>"));
+ printClientSideDetectedIssues(zeroWidthComponents, ac);
+ }
+ }
+
+ }
+
+ private void printClientSideDetectedIssues(
+ Set<ComponentConnector> zeroSized, ApplicationConnection ac) {
+
+ // keep track of already highlighted parents
+ HashSet<String> parents = new HashSet<String>();
+
+ for (final ComponentConnector connector : zeroSized) {
+ final ServerConnector parent = connector.getParent();
+ final String parentId = parent.getConnectorId();
+
+ final Label errorDetails = new Label(Util.getSimpleName(connector)
+ + "[" + connector.getConnectorId() + "]" + " inside "
+ + Util.getSimpleName(parent));
+
+ if (parent instanceof ComponentConnector) {
+ final ComponentConnector parentConnector = (ComponentConnector) parent;
+ if (!parents.contains(parentId)) {
+ parents.add(parentId);
+ Highlight.show(parentConnector, "yellow");
+ }
+
+ errorDetails.addMouseOverHandler(new MouseOverHandler() {
+ @Override
+ public void onMouseOver(MouseOverEvent event) {
+ Highlight.hideAll();
+ Highlight.show(parentConnector, "yellow");
+ Highlight.show(connector);
+ errorDetails.getElement().getStyle()
+ .setTextDecoration(TextDecoration.UNDERLINE);
+ }
+ });
+ errorDetails.addMouseOutHandler(new MouseOutHandler() {
+ @Override
+ public void onMouseOut(MouseOutEvent event) {
+ Highlight.hideAll();
+ errorDetails.getElement().getStyle()
+ .setTextDecoration(TextDecoration.NONE);
+ }
+ });
+ errorDetails.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ printState(connector);
+ Highlight.show(connector);
+ }
+ });
+
+ }
+
+ Highlight.show(connector);
+ content.add(errorDetails);
+
+ }
+ }
+
+ private void printLayoutError(ApplicationConnection ac, ValueMap valueMap,
+ SimpleTree root) {
+ final String pid = valueMap.getString("id");
+
+ // find connector
+ final ComponentConnector connector = (ComponentConnector) ConnectorMap
+ .get(ac).getConnector(pid);
+
+ if (connector == null) {
+ root.add(new SimpleTree("[" + pid + "] NOT FOUND"));
+ return;
+ }
+
+ Highlight.show(connector);
+
+ final SimpleTree errorNode = new SimpleTree(
+ Util.getSimpleName(connector) + " id: " + pid);
+ errorNode.addDomHandler(new MouseOverHandler() {
+ @Override
+ public void onMouseOver(MouseOverEvent event) {
+ Highlight.hideAll();
+ Highlight.show(connector);
+ ((Widget) event.getSource()).getElement().getStyle()
+ .setTextDecoration(TextDecoration.UNDERLINE);
+ }
+ }, MouseOverEvent.getType());
+ errorNode.addDomHandler(new MouseOutHandler() {
+ @Override
+ public void onMouseOut(MouseOutEvent event) {
+ Highlight.hideAll();
+ ((Widget) event.getSource()).getElement().getStyle()
+ .setTextDecoration(TextDecoration.NONE);
+ }
+ }, MouseOutEvent.getType());
+
+ errorNode.addDomHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ if (event.getNativeEvent().getEventTarget().cast() == errorNode
+ .getElement().getChild(1).cast()) {
+ printState(connector);
+ }
+ }
+ }, ClickEvent.getType());
+
+ VerticalPanel errorDetails = new VerticalPanel();
+
+ if (valueMap.containsKey("heightMsg")) {
+ errorDetails.add(new Label("Height problem: "
+ + valueMap.getString("heightMsg")));
+ }
+ if (valueMap.containsKey("widthMsg")) {
+ errorDetails.add(new Label("Width problem: "
+ + valueMap.getString("widthMsg")));
+ }
+ if (errorDetails.getWidgetCount() > 0) {
+ errorNode.add(errorDetails);
+ }
+ if (valueMap.containsKey("subErrors")) {
+ HTML l = new HTML(
+ "<em>Expand this node to show problems that may be dependent on this problem.</em>");
+ errorDetails.add(l);
+ JsArray<ValueMap> suberrors = valueMap
+ .getJSValueMapArray("subErrors");
+ for (int i = 0; i < suberrors.length(); i++) {
+ ValueMap value = suberrors.get(i);
+ printLayoutError(ac, value, errorNode);
+ }
+
+ }
+ root.add(errorNode);
+ }
+
+ private void findZeroSizeComponents(
+ Set<ComponentConnector> zeroHeightComponents,
+ Set<ComponentConnector> zeroWidthComponents,
+ ComponentConnector connector) {
+ Widget widget = connector.getWidget();
+ ComputedStyle computedStyle = new ComputedStyle(widget.getElement());
+ if (computedStyle.getIntProperty("height") == 0) {
+ zeroHeightComponents.add(connector);
+ }
+ if (computedStyle.getIntProperty("width") == 0) {
+ zeroWidthComponents.add(connector);
+ }
+ List<ServerConnector> children = connector.getChildren();
+ for (ServerConnector serverConnector : children) {
+ if (serverConnector instanceof ComponentConnector) {
+ findZeroSizeComponents(zeroHeightComponents,
+ zeroWidthComponents,
+ (ComponentConnector) serverConnector);
+ }
+ }
+ }
+
+ @Override
+ public void uidl(ApplicationConnection ac, ValueMap uidl) {
+ // NOP
+ }
+
+ private boolean isFindMode() {
+ return (highlightModeRegistration != null);
+ }
+
+ private void toggleFind() {
+ if (isFindMode()) {
+ stopFind();
+ } else {
+ startFind();
+ }
+ }
+
+ private void startFind() {
+ Highlight.hideAll();
+ if (!isFindMode()) {
+ highlightModeRegistration = Event
+ .addNativePreviewHandler(highlightModeHandler);
+ find.addStyleDependentName(VDebugWindow.STYLENAME_ACTIVE);
+ }
+ }
+
+ private void stopFind() {
+ if (isFindMode()) {
+ highlightModeRegistration.removeHandler();
+ highlightModeRegistration = null;
+ find.removeStyleDependentName(VDebugWindow.STYLENAME_ACTIVE);
+ }
+ }
+
+ private void printState(ComponentConnector connector) {
+ Highlight.show(connector);
+ AbstractComponentState state = connector.getState();
+
+ String html = getRowHTML("Id", connector.getConnectorId());
+ html += getRowHTML("Connector", Util.getSimpleName(connector));
+ html += getRowHTML("Widget", Util.getSimpleName(connector.getWidget()));
+ html += getRowHTML("Caption", state.caption);
+ html += getRowHTML("Description", state.description);
+ html += getRowHTML("Width", state.width + " (actual: "
+ + connector.getWidget().getOffsetWidth() + "px)");
+ html += getRowHTML("Height", state.height + " (actual: "
+ + connector.getWidget().getOffsetHeight() + "px)");
+ html += getRowHTML("Enabled", state.enabled);
+ html += getRowHTML("Read only", state.readOnly);
+ html += getRowHTML("Immediate", state.immediate);
+ html += getRowHTML("Error message", state.errorMessage);
+ html += getRowHTML("Primary stylename", state.primaryStyleName);
+ html += getRowHTML("Styles", state.styles);
+ html += getRowHTML("Resources", state.resources);
+
+ content.clear();
+ content.add(new HTML(html));
+ }
+
+ private String getRowHTML(String caption, Object value) {
+ return "<div class=\"" + VDebugWindow.STYLENAME
+ + "-row\"><span class=\"caption\">" + caption
+ + "</span><span class=\"value\">" + value + "</span></div>";
+ }
+
+ private final NativePreviewHandler highlightModeHandler = new NativePreviewHandler() {
+
+ @Override
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
+
+ if (event.getTypeInt() == Event.ONKEYDOWN
+ && event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
+ stopFind();
+ Highlight.hideAll();
+ return;
+ }
+ if (event.getTypeInt() == Event.ONMOUSEMOVE) {
+ Highlight.hideAll();
+ Element eventTarget = Util.getElementFromPoint(event
+ .getNativeEvent().getClientX(), event.getNativeEvent()
+ .getClientY());
+ if (VDebugWindow.get().getElement().isOrHasChild(eventTarget)) {
+ content.clear();
+ return;
+ }
+
+ for (ApplicationConnection a : ApplicationConfiguration
+ .getRunningApplications()) {
+ ComponentConnector connector = Util.getConnectorForElement(
+ a, a.getUIConnector().getWidget(), eventTarget);
+ if (connector == null) {
+ connector = Util.getConnectorForElement(a,
+ RootPanel.get(), eventTarget);
+ }
+ if (connector != null) {
+ printState(connector);
+ event.cancel();
+ event.consume();
+ event.getNativeEvent().stopPropagation();
+ return;
+ }
+ }
+ content.clear();
+ }
+ if (event.getTypeInt() == Event.ONCLICK) {
+ Highlight.hideAll();
+ event.cancel();
+ event.consume();
+ event.getNativeEvent().stopPropagation();
+ stopFind();
+ Element eventTarget = Util.getElementFromPoint(event
+ .getNativeEvent().getClientX(), event.getNativeEvent()
+ .getClientY());
+ for (ApplicationConnection a : ApplicationConfiguration
+ .getRunningApplications()) {
+ ComponentConnector connector = Util.getConnectorForElement(
+ a, a.getUIConnector().getWidget(), eventTarget);
+ if (connector == null) {
+ connector = Util.getConnectorForElement(a,
+ RootPanel.get(), eventTarget);
+ }
+
+ if (connector != null) {
+ printState(connector);
+ return;
+ }
+ }
+ }
+ event.cancel();
+ }
+
+ };
+
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/debug/internal/Highlight.java b/client/src/com/vaadin/client/debug/internal/Highlight.java
new file mode 100644
index 0000000000..6f41c71295
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/Highlight.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import java.util.HashSet;
+
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.BrowserInfo;
+import com.vaadin.client.ComponentConnector;
+import com.vaadin.client.ui.VWindow;
+
+/**
+ * Highlights a widget in the UI by overlaying a semi-transparent colored div.
+ * <p>
+ * Multiple highlights can be added, then selectively removed with
+ * {@link #hide(Element)} or all at once with {@link #hideAll()}.
+ * </p>
+ * <p>
+ * Note that highlights are intended to be short-term; highlights do not move or
+ * disappear with the highlighted widget, and it is also fairly likely that
+ * someone else calls {@link #hideAll()} eventually.
+ * </p>
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class Highlight {
+
+ private static final String DEFAULT_COLOR = "red";
+ private static final double DEFAULT_OPACITY = 0.3;
+ private static final int MIN_WIDTH = 3;
+ private static final int MIN_HEIGHT = 3;
+
+ static HashSet<Element> highlights;
+
+ /**
+ * Highlight the {@link Widget} for the given {@link ComponentConnector}.
+ * <p>
+ * Pass the returned {@link Element} to {@link #hide(Element)} to remove
+ * this particular highlight.
+ * </p>
+ *
+ * @param connector
+ * ComponentConnector
+ * @return Highlight element
+ */
+ static Element show(ComponentConnector connector) {
+ return show(connector, DEFAULT_COLOR);
+ }
+
+ /**
+ * Highlights the {@link Widget} for the given {@link ComponentConnector}
+ * using the given color.
+ * <p>
+ * Pass the returned {@link Element} to {@link #hide(Element)} to remove
+ * this particular highlight.
+ * </p>
+ *
+ * @param connector
+ * ComponentConnector
+ * @param color
+ * Color of highlight
+ * @return Highlight element
+ */
+ static Element show(ComponentConnector connector, String color) {
+ if (connector != null) {
+ Widget w = connector.getWidget();
+ return show(w, color);
+ }
+ return null;
+ }
+
+ /**
+ * Highlights the given {@link Widget}.
+ * <p>
+ * Pass the returned {@link Element} to {@link #hide(Element)} to remove
+ * this particular highlight.
+ * </p>
+ *
+ * @param widget
+ * Widget to highlight
+ * @return Highlight element
+ */
+ static Element show(Widget widget) {
+ return show(widget, DEFAULT_COLOR);
+ }
+
+ /**
+ * Highlight the given {@link Widget} using the given color.
+ * <p>
+ * Pass the returned {@link Element} to {@link #hide(Element)} to remove
+ * this particular highlight.
+ * </p>
+ *
+ * @param widget
+ * Widget to highlight
+ * @param color
+ * Color of highlight
+ * @return Highlight element
+ */
+ static Element show(Widget widget, String color) {
+ if (widget != null) {
+ if (highlights == null) {
+ highlights = new HashSet<Element>();
+ }
+
+ Element highlight = DOM.createDiv();
+ Style style = highlight.getStyle();
+ style.setTop(widget.getAbsoluteTop(), Unit.PX);
+ style.setLeft(widget.getAbsoluteLeft(), Unit.PX);
+ int width = widget.getOffsetWidth();
+ if (width < MIN_WIDTH) {
+ width = MIN_WIDTH;
+ }
+ style.setWidth(width, Unit.PX);
+ int height = widget.getOffsetHeight();
+ if (height < MIN_HEIGHT) {
+ height = MIN_HEIGHT;
+ }
+ style.setHeight(height, Unit.PX);
+ RootPanel.getBodyElement().appendChild(highlight);
+
+ style.setPosition(Position.ABSOLUTE);
+ style.setZIndex(VWindow.Z_INDEX + 1000);
+ style.setBackgroundColor(color);
+ style.setOpacity(DEFAULT_OPACITY);
+ if (BrowserInfo.get().isIE()) {
+ style.setProperty("filter", "alpha(opacity="
+ + (DEFAULT_OPACITY * 100) + ")");
+ }
+
+ highlights.add(highlight);
+
+ return highlight;
+ }
+ return null;
+ }
+
+ /**
+ * Hides the given highlight.
+ *
+ * @param highlight
+ * Highlight to hide
+ */
+ static void hide(Element highlight) {
+ if (highlight != null && highlight.getParentElement() != null) {
+ highlight.getParentElement().removeChild(highlight);
+ highlights.remove(highlight);
+ }
+ }
+
+ /**
+ * Hides all highlights
+ */
+ static void hideAll() {
+ if (highlights != null) {
+ for (Element highlight : highlights) {
+ if (highlight.getParentElement() != null) {
+ highlight.getParentElement().removeChild(highlight);
+ }
+ }
+ highlights = null;
+ }
+ }
+
+}
diff --git a/client/src/com/vaadin/client/debug/internal/Icon.java b/client/src/com/vaadin/client/debug/internal/Icon.java
new file mode 100644
index 0000000000..bbc7c3f41d
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/Icon.java
@@ -0,0 +1,46 @@
+package com.vaadin.client.debug.internal;
+
+public enum Icon {
+
+ SEARCH("&#xf002;"), //
+ OK("&#xf00c;"), //
+ REMOVE("&#xf00d;"), //
+ CLOSE("&#xf011;"), //
+ CLEAR("&#xf014;"), //
+ RESET_TIMER("&#xf017;"), //
+ MINIMIZE("&#xf066;"), //
+ WARNING("&#xf071;"), //
+ INFO("&#xf05a;"), //
+ ERROR("&#xf06a;"), //
+ HIGHLIGHT("&#xf05b;"), //
+ LOG("&#xf0c9;"), //
+ OPTIMIZE("&#xf0d0;"), //
+ HIERARCHY("&#xf0e8;"), //
+ MENU("&#xf013;"), //
+ NETWORK("&#xf0ec;"), //
+ ANALYZE("&#xf0f0;"), //
+ SCROLL_LOCK("&#xf023;"), //
+ DEVMODE_OFF("&#xf10c;"), //
+ DEVMODE_SUPER("&#xf111;"), //
+ DEVMODE_ON("&#xf110;"), //
+ // BAN_CIRCLE("&#xf05e;"), //
+ MAXIMIZE("&#xf065;"), //
+ RESET("&#xf021;"), //
+ PERSIST("&#xf02e"); //
+
+ private String id;
+
+ private Icon(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ return "<i data-icon=\"" + id + "\"></i>";
+ }
+
+ public String getId() {
+ return id;
+ }
+
+}
diff --git a/client/src/com/vaadin/client/debug/internal/Level.java b/client/src/com/vaadin/client/debug/internal/Level.java
new file mode 100644
index 0000000000..3ce314d5cb
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/Level.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+/**
+ * Log level for debug messages.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+enum Level {
+ DEBUG, LOG, WARNING, ERROR
+}
diff --git a/client/src/com/vaadin/client/debug/internal/LogSection.java b/client/src/com/vaadin/client/debug/internal/LogSection.java
new file mode 100644
index 0000000000..0285524558
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/LogSection.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.storage.client.Storage;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ValueMap;
+
+/**
+ * Displays the log messages.
+ * <p>
+ * Scroll lock state is persisted.
+ * </p>
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+class LogSection implements Section {
+
+ // If scroll is not locked, content will be scrolled after delay
+ private static final int SCROLL_DELAY = 100;
+ private Timer scrollTimer = null;
+
+ // TODO should be persisted
+ // log content limit
+ private int limit = 500;
+
+ private final DebugButton tabButton = new DebugButton(Icon.LOG,
+ "Debug message log");
+
+ private final HTML content = new HTML();
+ private final Element contentElement;
+ private final FlowPanel controls = new FlowPanel();
+
+ private final Button clear = new DebugButton(Icon.CLEAR, "Clear log");
+ private final Button reset = new DebugButton(Icon.RESET_TIMER,
+ "Reset timer");
+ private final Button scroll = new DebugButton(Icon.SCROLL_LOCK,
+ "Scroll lock");
+
+ public LogSection() {
+ contentElement = content.getElement();
+ content.setStylePrimaryName(VDebugWindow.STYLENAME + "-log");
+
+ // clear log button
+ controls.add(clear);
+ clear.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON);
+ clear.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ clear();
+ }
+ });
+
+ // reset timer button
+ controls.add(reset);
+ reset.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON);
+ reset.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ resetTimer();
+ }
+ });
+
+ // scroll lock toggle
+ controls.add(scroll);
+ scroll.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON);
+ scroll.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ toggleScrollLock();
+ }
+ });
+
+ // select message if row is clicked
+ content.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ Element el = Element
+ .as(event.getNativeEvent().getEventTarget());
+ while (!el.getClassName().contains(
+ VDebugWindow.STYLENAME + "-message")) {
+ el = el.getParentElement();
+ if (el == contentElement) {
+ // clicked something else
+ return;
+ }
+ }
+ selectText(el);
+ }
+ });
+
+ }
+
+ /**
+ * Toggles scroll lock, writes state to persistent storage.
+ */
+ void toggleScrollLock() {
+ setScrollLock(scrollTimer != null);
+
+ Storage storage = Storage.getLocalStorageIfSupported();
+ if (storage == null) {
+ return;
+ }
+ VDebugWindow.writeState(storage, "log-scrollLock", scrollTimer == null);
+ }
+
+ /**
+ * Activates or deactivates scroll lock
+ *
+ * @param locked
+ */
+ void setScrollLock(boolean locked) {
+ if (locked && scrollTimer != null) {
+ scrollTimer.cancel();
+ scrollTimer = null;
+
+ } else if (!locked && scrollTimer == null) {
+ scrollTimer = new Timer() {
+ @Override
+ public void run() {
+ Element el = (Element) contentElement.getLastChild();
+ if (el != null) {
+ el = el.getFirstChildElement();
+ if (el != null) {
+ el.scrollIntoView();
+ }
+ }
+ }
+ };
+
+ }
+ scroll.setStyleDependentName(VDebugWindow.STYLENAME_ACTIVE, locked);
+
+ }
+
+ private native void selectText(Element el)
+ /*-{
+ if ($doc.selection && $doc.selection.createRange) {
+ var r = $doc.selection.createRange();
+ r.moveToElementText(el);
+ r.select();
+ } else if ($doc.createRange && $wnd.getSelection) {
+ var r = $doc.createRange();
+ r.selectNode(el);
+ var selection = $wnd.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(r);
+ }
+ }-*/;
+
+ private void clear() {
+ contentElement.setInnerText("");
+ }
+
+ private void applyLimit() {
+ while (contentElement.getChildCount() > limit) {
+ contentElement.removeChild(contentElement.getFirstChild());
+ }
+ }
+
+ /**
+ * Sets the log row limit.
+ *
+ * @param limit
+ */
+ public void setLimit(int limit) {
+ this.limit = limit;
+ applyLimit();
+
+ // TODO shoud be persisted
+ }
+
+ /**
+ * Gets the current log row limit.
+ *
+ * @return
+ */
+ public int getLimit() {
+ // TODO should be read from persistent storage
+ return limit;
+ }
+
+ @Override
+ public DebugButton getTabButton() {
+ return tabButton;
+ }
+
+ @Override
+ public Widget getControls() {
+ return controls;
+ }
+
+ @Override
+ public Widget getContent() {
+ return content;
+ }
+
+ @Override
+ public void show() {
+ Storage storage = Storage.getLocalStorageIfSupported();
+ if (storage == null) {
+ return;
+ }
+ setScrollLock(VDebugWindow.readState(storage, "log-scrollLock", false));
+ }
+
+ @Override
+ public void hide() {
+ // remove timer
+ setScrollLock(true);
+ }
+
+ /**
+ * Schedules a scoll if scroll lock is not active.
+ */
+ private void maybeScroll() {
+ if (scrollTimer != null) {
+ scrollTimer.cancel();
+ scrollTimer.schedule(SCROLL_DELAY);
+ }
+ }
+
+ /**
+ * Resets the timer and inserts a log row indicating this.
+ */
+ private void resetTimer() {
+ int sinceStart = VDebugWindow.getMillisSinceStart();
+ int sinceReset = VDebugWindow.resetTimer();
+ Element row = DOM.createDiv();
+ row.addClassName(VDebugWindow.STYLENAME + "-reset");
+ row.setInnerHTML(Icon.RESET_TIMER + " Timer reset");
+ row.setTitle(VDebugWindow.getTimingTooltip(sinceStart, sinceReset));
+ contentElement.appendChild(row);
+ maybeScroll();
+ }
+
+ /**
+ * Adds a row to the log, applies the log row limit by removing old rows if
+ * needed, and scrolls new row into view if scroll lock is not active.
+ *
+ * @param level
+ * @param category
+ * @param msg
+ * @return
+ */
+ private Element addRow(Level level, String category, String msg) {
+ int sinceReset = VDebugWindow.getMillisSinceReset();
+ int sinceStart = VDebugWindow.getMillisSinceStart();
+
+ Element row = DOM.createDiv();
+ row.addClassName(VDebugWindow.STYLENAME + "-row");
+ row.addClassName(level.name());
+
+ String inner = "<span class='" + VDebugWindow.STYLENAME + "-"
+ + category + "'></span><span class='" + VDebugWindow.STYLENAME
+ + "-time' title='"
+ + VDebugWindow.getTimingTooltip(sinceStart, sinceReset) + "'>"
+ + sinceReset + "ms</span><span class='"
+ + VDebugWindow.STYLENAME + "-message'>" + msg + "</span>";
+ row.setInnerHTML(inner);
+
+ contentElement.appendChild(row);
+ applyLimit();
+
+ maybeScroll();
+
+ return row;
+ }
+
+ /*
+ * LOGGING methods follow.
+ *
+ * NOTE that these are still subject to change.
+ */
+
+ @Override
+ public void log(Level level, String msg) {
+ addRow(level, "none", msg);
+ }
+
+ public void log(Level level, String category, String msg) {
+ addRow(level, category, msg);
+ }
+
+ @Override
+ public void meta(ApplicationConnection ac, ValueMap meta) {
+ log(Level.DEBUG, "Meta: " + meta.toSource());
+ }
+
+ @Override
+ public void uidl(ApplicationConnection ac, ValueMap uidl) {
+ log(Level.DEBUG, "UIDL: " + uidl.toSource());
+ }
+
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/debug/internal/NetworkSection.java b/client/src/com/vaadin/client/debug/internal/NetworkSection.java
new file mode 100644
index 0000000000..ff6466651b
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/NetworkSection.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.VUIDLBrowser;
+import com.vaadin.client.ValueMap;
+
+/**
+ * Displays network activity; requests and responses.
+ *
+ * Currently only displays responses in a simple manner.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class NetworkSection implements Section {
+
+ private final int maxSize = 10;
+
+ private final DebugButton tabButton = new DebugButton(Icon.NETWORK,
+ "Communication");
+
+ private final HorizontalPanel controls = new HorizontalPanel();
+ private final FlowPanel content = new FlowPanel();
+
+ @Override
+ public DebugButton getTabButton() {
+ return tabButton;
+ }
+
+ @Override
+ public Widget getControls() {
+ return controls;
+ }
+
+ @Override
+ public Widget getContent() {
+ return content;
+ }
+
+ @Override
+ public void show() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void hide() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void log(Level level, String msg) {
+ // NOP
+ }
+
+ @Override
+ public void meta(ApplicationConnection ac, ValueMap meta) {
+ // NOP
+ }
+
+ public void uidl(ApplicationConnection ac, ValueMap uidl) {
+ int sinceStart = VDebugWindow.getMillisSinceStart();
+ int sinceReset = VDebugWindow.getMillisSinceReset();
+ VUIDLBrowser vuidlBrowser = new VUIDLBrowser(uidl, ac);
+ vuidlBrowser.addStyleName(VDebugWindow.STYLENAME + "-row");
+ // TODO style this
+ /*-
+ vuidlBrowser.setText("<span class=\"" + VDebugWindow.STYLENAME
+ + "-time\">" + sinceReset + "ms</span><span class=\""
+ + VDebugWindow.STYLENAME + "-message\">response</span>");
+ -*/
+ vuidlBrowser.setText("Response @ " + sinceReset + "ms");
+ vuidlBrowser.setTitle(VDebugWindow.getTimingTooltip(sinceStart,
+ sinceReset));
+ vuidlBrowser.close();
+ content.add(vuidlBrowser);
+ while (content.getWidgetCount() > maxSize) {
+ content.remove(0);
+ }
+ }
+
+}
diff --git a/client/src/com/vaadin/client/debug/internal/Section.java b/client/src/com/vaadin/client/debug/internal/Section.java
new file mode 100644
index 0000000000..7c662bc035
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/Section.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ValueMap;
+
+/**
+ * A Section is displayed as a tab in the {@link VDebugWindow}.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public interface Section {
+
+ /**
+ * Returns a button that will be used to activate this section, displayed as
+ * a tab in {@link VDebugWindow}.
+ * <p>
+ * <em>The same instance <b>must</b> be returned each time this method is called.</em>
+ * </p>
+ * <p>
+ * The button should preferably only have an icon (no caption), and should
+ * have a longer description as title (tooltip).
+ * </p>
+ *
+ * @return section id
+ */
+ public DebugButton getTabButton();
+
+ /**
+ * Returns a widget that is placed on top of the Section content when the
+ * Section (tab) is active in the {@link VDebugWindow}.
+ *
+ * @return section controls
+ */
+ public Widget getControls();
+
+ /**
+ * Returns a widget that is the main content of the section, displayed when
+ * the section is active in the {@link VDebugWindow}.
+ *
+ * @return
+ */
+ public Widget getContent();
+
+ /**
+ * Called when the section is activated in {@link VDebugWindow}. Provides an
+ * opportunity to e.g start timers, add listeners etc.
+ */
+ public void show();
+
+ /**
+ * Called when the section is deactivated in {@link VDebugWindow}. Provides
+ * an opportunity to e.g stop timers, remove listeners etc.
+ */
+ public void hide();
+
+ public void log(Level level, String msg);
+
+ public void meta(ApplicationConnection ac, ValueMap meta);
+
+ public void uidl(ApplicationConnection ac, ValueMap uidl);
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/debug/internal/VDebugWindow.java b/client/src/com/vaadin/client/debug/internal/VDebugWindow.java
new file mode 100644
index 0000000000..86de1884ef
--- /dev/null
+++ b/client/src/com/vaadin/client/debug/internal/VDebugWindow.java
@@ -0,0 +1,1086 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.debug.internal;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+import com.google.gwt.core.client.Duration;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Cursor;
+import com.google.gwt.dom.client.Style.Overflow;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseEvent;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.http.client.UrlBuilder;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.storage.client.Storage;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.Window.Location;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ValueMap;
+import com.vaadin.client.ui.VOverlay;
+
+/**
+ * Debug window implementation.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public final class VDebugWindow extends VOverlay {
+
+ // CSS classes
+ static final String STYLENAME = "v-debugwindow";
+ static final String STYLENAME_BUTTON = STYLENAME + "-button";
+ static final String STYLENAME_ACTIVE = "active";
+
+ protected static final String STYLENAME_HEAD = STYLENAME + "-head";
+ protected static final String STYLENAME_TABS = STYLENAME + "-tabs";
+ protected static final String STYLENAME_TAB = STYLENAME + "-tab";
+ protected static final String STYLENAME_CONTROLS = STYLENAME + "-controls";
+ protected static final String STYLENAME_SECTION_HEAD = STYLENAME
+ + "-section-head";
+ protected static final String STYLENAME_CONTENT = STYLENAME + "-content";
+ protected static final String STYLENAME_SELECTED = "selected";
+
+ // drag this far before actually moving window
+ protected static final int MOVE_TRESHOLD = 5;
+
+ // window minimum sizes
+ protected static final int MIN_HEIGHT = 40;
+ protected static final int HANDLE_SIZE = 5;
+
+ // identifiers for localStorage
+ private static final String STORAGE_PREFIX = "v-debug-";
+ private static final String STORAGE_FULL_X = "x";
+ private static final String STORAGE_FULL_Y = "y";
+ private static final String STORAGE_FULL_W = "w";
+ private static final String STORAGE_FULL_H = "h";
+ private static final String STORAGE_MIN_X = "mx";
+ private static final String STORAGE_MIN_Y = "my";
+ private static final String STORAGE_ACTIVE_SECTION = "t";
+ private static final String STORAGE_IS_MINIMIZED = "m";
+ private static final String STORAGE_FONT_SIZE = "s";
+
+ // state, these are persisted
+ protected Section activeSection;
+ protected boolean minimized = false;
+ protected int fullX = -10;
+ protected int fullY = -10;
+ protected int fullW = 300;
+ protected int fullH = 150;
+ protected int minX = -10;
+ protected int minY = 10;
+ protected int fontSize = 1; // 0-2
+
+ // Timers since application start, and last timer reset
+ private static final Duration start = new Duration();
+ private static Duration lastReset = start;
+
+ // outer panel
+ protected FlowPanel window = new FlowPanel();
+ // top (tabs + controls)
+ protected FlowPanel head = new FlowPanel();
+ protected FlowPanel tabs = new FlowPanel();
+ protected FlowPanel controls = new FlowPanel();
+ protected Button minimize = new DebugButton(Icon.MINIMIZE, "Minimize");
+ protected Button menu = new DebugButton(Icon.MENU, "Menu");
+ protected Button close = new DebugButton(Icon.CLOSE, "Close");
+
+ // menu
+ protected Menu menuPopup = new Menu();
+
+ // section specific area
+ protected FlowPanel sectionHead = new FlowPanel();
+ // content wrapper
+ protected SimplePanel content = new SimplePanel();
+
+ // sections
+ protected ArrayList<Section> sections = new ArrayList<Section>();
+
+ // handles resizing (mouse)
+ protected ResizeHandler resizeHandler = new ResizeHandler();
+ protected HandlerRegistration resizeReg = null;
+ protected HandlerRegistration resizeReg2 = null;
+
+ // handles window movement (mouse)
+ protected MoveHandler moveHandler = new MoveHandler();
+ protected HandlerRegistration moveReg = null;
+
+ // TODO this class should really be a singleton.
+ static VDebugWindow instance;
+
+ /**
+ * This class should only be instantiated by the framework, use
+ * {@link #get()} instead to get the singleton instance.
+ * <p>
+ * {@link VDebugWindow} provides windowing functionality and shows
+ * {@link Section}s added with {@link #addSection(Section)} as tabs.
+ * </p>
+ * <p>
+ * {@link Section#getTabButton()} is called to obtain a unique id for the
+ * Sections; the id should actually be an identifier for an icon in the
+ * icon-font in use.
+ * </p>
+ * <p>
+ * {@link Section#getControls()} and {@link Section#getContent()} is called
+ * when the Section is activated (displayed). Additionally
+ * {@link Section#show()} is called to allow the Section to initialize
+ * itself as needed when shown. Conversely {@link Section#hide()} is called
+ * when the Section is deactivated.
+ * </p>
+ * <p>
+ * Sections should take care to prefix CSS classnames used with
+ * {@link VDebugWindow}.{@link #STYLENAME} to avoid that application theme
+ * interferes with the debug window content.
+ * </p>
+ * <p>
+ * Some of the window state, such as position and size, is persisted to
+ * localStorage. Sections can use
+ * {@link #writeState(Storage, String, Object)} and
+ * {@link #readState(Storage, String, String)} (and relatives) to write and
+ * read own persisted settings, keys will automatically be prefixed with
+ * {@value #STORAGE_PREFIX}.
+ * </p>
+ */
+ public VDebugWindow() {
+ super(false, false);
+ instance = this;
+ getElement().getStyle().setOverflow(Overflow.HIDDEN);
+ setStylePrimaryName(STYLENAME);
+
+ setWidget(window);
+ window.add(head);
+ head.add(tabs);
+ head.add(controls);
+ head.add(sectionHead);
+ window.add(content);
+
+ head.setStylePrimaryName(STYLENAME_HEAD);
+ tabs.setStylePrimaryName(STYLENAME_TABS);
+ controls.setStylePrimaryName(STYLENAME_CONTROLS);
+ sectionHead.setStylePrimaryName(STYLENAME_SECTION_HEAD);
+ content.setStylePrimaryName(STYLENAME_CONTENT);
+
+ // add controls TODO move these
+ controls.add(menu);
+ menu.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ menuPopup.showRelativeTo(menu);
+ }
+ });
+
+ controls.add(minimize);
+ minimize.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ toggleMinimized();
+ writeStoredState();
+ }
+ });
+ controls.add(close);
+ close.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ close();
+ }
+ });
+
+ Style s = content.getElement().getStyle();
+ s.setOverflow(Overflow.AUTO);
+
+ // window can be moved by dragging header
+ moveReg = head.addDomHandler(moveHandler, MouseDownEvent.getType());
+ // resize from all sides and corners
+ resizeReg = content.addDomHandler(resizeHandler,
+ MouseDownEvent.getType());
+ // changes mouse pointer when hovering sides / corners
+ resizeReg2 = content.addDomHandler(resizeHandler,
+ MouseMoveEvent.getType());
+ }
+
+ /**
+ * Gets the {@link #VDebugWindow()} singleton instance.
+ *
+ * @return
+ */
+ public static VDebugWindow get() {
+ if (instance == null) {
+ instance = new VDebugWindow();
+ }
+ return instance;
+ }
+
+ /**
+ * Closes the window and stops visual logging.
+ */
+ void close() {
+ // TODO disable even more
+ if (resizeReg != null) {
+ resizeReg.removeHandler();
+ resizeReg2.removeHandler();
+ moveReg.removeHandler();
+ }
+ Highlight.hideAll();
+ hide();
+
+ }
+
+ boolean isClosed() {
+ return !isShowing();
+ }
+
+ /**
+ * Reads the stored state from localStorage.
+ */
+ private void readStoredState() {
+ Storage storage = Storage.getLocalStorageIfSupported();
+ if (storage == null) {
+ return;
+ }
+
+ fullX = readState(storage, STORAGE_FULL_X, -510);
+ fullY = readState(storage, STORAGE_FULL_Y, -230);
+ fullW = readState(storage, STORAGE_FULL_W, 500);
+ fullH = readState(storage, STORAGE_FULL_H, 150);
+ minX = readState(storage, STORAGE_MIN_X, -40);
+ minY = readState(storage, STORAGE_MIN_Y, -70);
+ setFontSize(readState(storage, STORAGE_FONT_SIZE, 1));
+
+ activateSection(readState(storage, STORAGE_ACTIVE_SECTION, 0));
+
+ setMinimized(readState(storage, STORAGE_IS_MINIMIZED, false));
+
+ applyPositionAndSize();
+ }
+
+ /**
+ * Writes the persistent state to localStorage.
+ */
+ private void writeStoredState() {
+ if (isClosed()) {
+ return;
+ }
+ Storage storage = Storage.getLocalStorageIfSupported();
+ if (storage == null) {
+ return;
+ }
+
+ writeState(storage, STORAGE_FULL_X, fullX);
+ writeState(storage, STORAGE_FULL_Y, fullY);
+ writeState(storage, STORAGE_FULL_W, fullW);
+ writeState(storage, STORAGE_FULL_H, fullH);
+ writeState(storage, STORAGE_MIN_X, minX);
+ writeState(storage, STORAGE_MIN_Y, minY);
+ writeState(storage, STORAGE_FONT_SIZE, fontSize);
+
+ if (activeSection != null) {
+ writeState(storage, STORAGE_ACTIVE_SECTION,
+ activeSection.getTabButton());
+ }
+
+ writeState(storage, STORAGE_IS_MINIMIZED, minimized);
+ }
+
+ /**
+ * Writes the given value to the given {@link Storage} using the given key
+ * (automatically prefixed with {@value #STORAGE_PREFIX}).
+ *
+ * @param storage
+ * @param key
+ * @param value
+ */
+ static void writeState(Storage storage, String key, Object value) {
+ storage.setItem(STORAGE_PREFIX + key, String.valueOf(value));
+ }
+
+ /**
+ * Returns the item with the given key (automatically prefixed with
+ * {@value #STORAGE_PREFIX}) as an int from the given {@link Storage},
+ * returning the given default value instead if not successful (e.g missing
+ * item).
+ *
+ * @param storage
+ * @param key
+ * @param def
+ * @return stored or default value
+ */
+ static int readState(Storage storage, String key, int def) {
+ try {
+ return Integer.parseInt(storage.getItem(STORAGE_PREFIX + key));
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /**
+ * Returns the item with the given key (automatically prefixed with
+ * {@value #STORAGE_PREFIX}) as a boolean from the given {@link Storage},
+ * returning the given default value instead if not successful (e.g missing
+ * item).
+ *
+ * @param storage
+ * @param key
+ * @param def
+ * @return stored or default value
+ */
+ static boolean readState(Storage storage, String key, boolean def) {
+ try {
+ return Boolean.parseBoolean(storage.getItem(STORAGE_PREFIX + key));
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /**
+ * Returns the item with the given key (automatically prefixed with
+ * {@value #STORAGE_PREFIX}) as a String from the given {@link Storage},
+ * returning the given default value instead if not successful (e.g missing
+ * item).
+ *
+ * @param storage
+ * @param key
+ * @param def
+ * @return stored or default value
+ */
+ static String readState(Storage storage, String key, String def) {
+ String val = storage.getItem(STORAGE_PREFIX + key);
+ return val != null ? val : def;
+ }
+
+ /**
+ * Resets (clears) the stored state from localStorage.
+ */
+ private void resetStoredState() {
+ Storage storage = Storage.getLocalStorageIfSupported();
+ if (storage == null) {
+ return;
+ }
+ // note: length is live
+ for (int i = 0; i < storage.getLength();) {
+ String key = storage.key(i);
+ if (key.startsWith(STORAGE_PREFIX)) {
+ removeState(storage, key.substring(STORAGE_PREFIX.length()));
+ } else {
+ i++;
+ }
+ }
+ }
+
+ /**
+ * Removes the item with the given key (automatically prefixed with
+ * {@value #STORAGE_PREFIX}) from the given {@link Storage}.
+ *
+ * @param storage
+ * @param key
+ */
+ private void removeState(Storage storage, String key) {
+ storage.removeItem(STORAGE_PREFIX + key);
+ }
+
+ /**
+ * Applies the appropriate instance variables for width, height, x, y
+ * depending on if the window is minimized or not.
+ *
+ * If the value is negative, the window is positioned that amount of pixels
+ * from the right/bottom instead of left/top.
+ *
+ * Finally, the position is bounds-checked so that the window is not moved
+ * off-screen (the adjusted values are not saved).
+ */
+ private void applyPositionAndSize() {
+ int x = 0;
+ int y = 0;
+ if (minimized) {
+ x = minX;
+ if (minX < 0) {
+ x = Window.getClientWidth() + minX;
+ }
+ y = minY;
+ if (minY < 0) {
+ y = Window.getClientHeight() + minY;
+ }
+
+ } else {
+ x = fullX;
+ if (fullX < 0) {
+ x = Window.getClientWidth() + fullX;
+ }
+ y = fullY;
+ if (y < 0) {
+ y = Window.getClientHeight() + fullY;
+ }
+ content.setWidth(fullW + "px");
+ content.setHeight(fullH + "px");
+ }
+
+ // bounds check
+ if (x < 0) {
+ x = 0;
+ }
+ if (x > Window.getClientWidth() - getOffsetWidth()) {
+ // not allowed off-screen to the right
+ x = Window.getClientWidth() - getOffsetWidth();
+ }
+ if (y > Window.getClientHeight() - getOffsetHeight()) {
+ y = Window.getClientHeight() - getOffsetHeight();
+ }
+ if (y < 0) {
+ y = 0;
+ }
+
+ setPopupPosition(x, y);
+ }
+
+ /**
+ * Reads position and size from the DOM to local variables (which in turn
+ * can be stored to localStorage)
+ */
+ private void readPositionAndSize() {
+ int x = getPopupLeft();
+ int fromRight = Window.getClientWidth() - x - getOffsetWidth();
+ if (fromRight < x) {
+ x -= Window.getClientWidth();
+ }
+
+ int y = getPopupTop();
+ int fromBottom = Window.getClientHeight() - y - getOffsetHeight();
+ if (fromBottom < y) {
+ y -= Window.getClientHeight();
+ }
+
+ if (minimized) {
+ minY = y;
+ minX = x;
+ } else {
+ fullY = y;
+ fullX = x;
+ fullW = content.getOffsetWidth();
+ fullH = content.getOffsetHeight();
+ }
+
+ }
+
+ /**
+ * Adds the given {@link Section} as a tab in the {@link VDebugWindow} UI.
+ * {@link Section#getTabButton()} is called to obtain a button which is used
+ * tab.
+ *
+ * @param section
+ */
+ void addSection(final Section section) {
+ Button b = section.getTabButton();
+ b.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ activateSection(section);
+ writeStoredState();
+ }
+ });
+ b.setStylePrimaryName(STYLENAME_TAB);
+ tabs.add(b);
+ sections.add(section);
+
+ if (activeSection == null) {
+ activateSection(section);
+ }
+ }
+
+ /**
+ * Activates the given {@link Section}
+ *
+ * @param section
+ */
+ void activateSection(Section section) {
+ if (section != null && section != activeSection) {
+ Highlight.hideAll();
+ // remove old stuff
+ if (activeSection != null) {
+ activeSection.hide();
+ content.remove(activeSection.getContent());
+ sectionHead.remove(activeSection.getControls());
+ }
+ // update tab styles
+ for (int i = 0; i < tabs.getWidgetCount(); i++) {
+ Widget tab = tabs.getWidget(i);
+ tab.setStyleDependentName(STYLENAME_SELECTED,
+ tab == section.getTabButton());
+ }
+ // add new stuff
+ content.add(section.getContent());
+ sectionHead.add(section.getControls());
+ activeSection = section;
+ activeSection.show();
+ }
+ }
+
+ void activateSection(int n) {
+ if (n < sections.size()) {
+ activateSection(sections.get(n));
+ }
+ }
+
+ /**
+ * Toggles the window between minimized and full states.
+ */
+ private void toggleMinimized() {
+ setMinimized(!minimized);
+ writeStoredState();
+ }
+
+ /**
+ * Sets whether or not the window is minimized.
+ *
+ * @param minimized
+ */
+ private void setMinimized(boolean minimized) {
+ this.minimized = minimized;
+
+ tabs.setVisible(!minimized);
+ content.setVisible(!minimized);
+ sectionHead.setVisible(!minimized);
+ menu.setVisible(!minimized);
+
+ applyPositionAndSize();
+ }
+
+ /**
+ * Sets the font size in use.
+ *
+ * @param size
+ */
+ private void setFontSize(int size) {
+ removeStyleDependentName("size" + fontSize);
+ fontSize = size;
+ addStyleDependentName("size" + size);
+ }
+
+ /**
+ * Gets the font size currently in use.
+ *
+ * @return
+ */
+ private int getFontSize() {
+ return fontSize;
+ }
+
+ /**
+ * Gets the milliseconds since application start.
+ *
+ * @return
+ */
+ static int getMillisSinceStart() {
+ return start.elapsedMillis();
+ }
+
+ /**
+ * Gets the milliseconds since last {@link #resetTimer()} call.
+ *
+ * @return
+ */
+ static int getMillisSinceReset() {
+ return lastReset.elapsedMillis();
+ }
+
+ /**
+ * Resets the timer.
+ *
+ * @return Milliseconds elapsed since the timer was last reset.
+ */
+ static int resetTimer() {
+ int sinceLast = lastReset.elapsedMillis();
+ lastReset = new Duration();
+ return sinceLast;
+ }
+
+ /**
+ * Gets a nicely formatted string with timing information suitable for
+ * display in tooltips.
+ *
+ * @param sinceStart
+ * @param sinceReset
+ * @return
+ */
+ static String getTimingTooltip(int sinceStart, int sinceReset) {
+ String title = formatDuration(sinceStart) + " since start";
+ title += ", &#10;" + formatDuration(sinceReset) + " since timer reset";
+ title += " &#10;@ "
+ + DateTimeFormat.getFormat("HH:mm:ss.SSS").format(new Date());
+ return title;
+ }
+
+ /**
+ * Formats the given milliseconds as hours, minutes, seconds and
+ * milliseconds.
+ *
+ * @param ms
+ * @return
+ */
+ static String formatDuration(int ms) {
+ NumberFormat fmt = NumberFormat.getFormat("00");
+ String seconds = fmt.format((ms / 1000) % 60);
+ String minutes = fmt.format((ms / (1000 * 60)) % 60);
+ String hours = fmt.format((ms / (1000 * 60 * 60)) % 24);
+
+ String millis = NumberFormat.getFormat("000").format(ms % 1000);
+
+ return hours + "h " + minutes + "m " + seconds + "s " + millis + "ms";
+ }
+
+ /**
+ * Called when the window is initialized.
+ */
+ void init() {
+
+ show();
+ readStoredState();
+
+ Window.addResizeHandler(new com.google.gwt.event.logical.shared.ResizeHandler() {
+
+ Timer t = new Timer() {
+ @Override
+ public void run() {
+ applyPositionAndSize();
+ }
+ };
+
+ @Override
+ public void onResize(ResizeEvent event) {
+ t.cancel();
+ // TODO less
+ t.schedule(1000);
+ }
+ });
+ }
+
+ /*
+ * LOGGING methods follow
+ *
+ * NOTE that these are subject to change and only implemented in the current
+ * manner for compatibility.
+ *
+ * TODO Sections should listen to logging events in the future
+ */
+
+ /**
+ * Called when a generic logging message is received
+ *
+ * @param level
+ * @param msg
+ */
+ void log(Level level, String msg) {
+ if (isClosed()) {
+ return;
+ }
+ for (Section s : sections) {
+ s.log(level, msg);
+ }
+ }
+
+ /**
+ * Called when the result from analyzeLayouts is received.
+ *
+ * @param ac
+ * @param meta
+ */
+ void meta(ApplicationConnection ac, ValueMap meta) {
+ if (isClosed()) {
+ return;
+ }
+ for (Section s : sections) {
+ s.meta(ac, meta);
+ }
+ }
+
+ /**
+ * Called when a response is received
+ *
+ * @param ac
+ * @param uidl
+ */
+ void uidl(ApplicationConnection ac, ValueMap uidl) {
+ if (isClosed()) {
+ return;
+ }
+ for (Section s : sections) {
+ s.uidl(ac, uidl);
+ }
+ }
+
+ /*
+ * Inner classes
+ */
+
+ /**
+ * Popup menu for {@link VDebugWindow}.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+ protected class Menu extends VOverlay {
+ FlowPanel content = new FlowPanel();
+
+ DebugButton[] sizes = new DebugButton[] {
+ new DebugButton(null, "Small", "A"),
+ new DebugButton(null, "Medium", "A"),
+ new DebugButton(null, "Large", "A") };
+
+ DebugButton[] modes = new DebugButton[] {
+ new DebugButton(Icon.DEVMODE_OFF,
+ "Debug only (causes page reload)"),
+ new DebugButton(Icon.DEVMODE_ON, "DevMode (causes page reload)"),
+ new DebugButton(Icon.DEVMODE_SUPER,
+ "SuperDevMode (causes page reload)") };
+
+ Menu() {
+ super(true, true);
+ setWidget(content);
+
+ setStylePrimaryName(STYLENAME + "-menu");
+ content.setStylePrimaryName(STYLENAME + "-menu-content");
+
+ FlowPanel size = new FlowPanel();
+ content.add(size);
+
+ final ClickHandler sizeHandler = new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ for (int i = 0; i < sizes.length; i++) {
+ Button b = sizes[i];
+ if (b == event.getSource()) {
+ setSize(i);
+ }
+ }
+ hide();
+ }
+ };
+ for (int i = 0; i < sizes.length; i++) {
+ Button b = sizes[i];
+ b.setStyleDependentName("size" + i, true);
+ b.addClickHandler(sizeHandler);
+ size.add(b);
+ }
+
+ FlowPanel mode = new FlowPanel();
+ content.add(mode);
+ final ClickHandler modeHandler = new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ for (int i = 0; i < modes.length; i++) {
+ Button b = modes[i];
+ if (b == event.getSource()) {
+ setDevMode(i);
+ }
+ }
+ hide();
+ }
+ };
+ modes[getDevMode()].setActive(true);
+ for (int i = 0; i < modes.length; i++) {
+ Button b = modes[i];
+ b.addClickHandler(modeHandler);
+ mode.add(b);
+ }
+
+ Button reset = new DebugButton(Icon.RESET, "Restore defaults.",
+ " Reset");
+ reset.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ resetStoredState();
+ readStoredState();
+ hide();
+ }
+ });
+ content.add(reset);
+ }
+
+ private void setSize(int size) {
+ for (int i = 0; i < sizes.length; i++) {
+ Button b = sizes[i];
+ b.setStyleDependentName(STYLENAME_ACTIVE, i == size);
+ }
+ setFontSize(size);
+ writeStoredState();
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ setSize(getFontSize());
+ }
+
+ private int getDevMode() {
+ if (Location.getParameter("superdevmode") != null) {
+ return 2;
+ } else if (Location.getParameter("gwt.codesvr") != null) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ private void setDevMode(int mode) {
+ UrlBuilder u = Location.createUrlBuilder();
+ switch (mode) {
+ case 2:
+ u.setParameter("superdevmode", "");
+ u.removeParameter("gwt.codesvr");
+ break;
+ case 1:
+ u.setParameter("gwt.codesvr", "localhost:9997");
+ u.removeParameter("superdevmode");
+ break;
+ default:
+ u.removeParameter("gwt.codesvr");
+ u.removeParameter("superdevmode");
+ }
+ Location.assign(u.buildString());
+ }
+
+ }
+
+ /**
+ * Handler for moving window.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+ protected class MoveHandler implements MouseDownHandler,
+ NativePreviewHandler {
+
+ HandlerRegistration handler;
+ int startX;
+ int startY;
+ int startTop;
+ int startLeft;
+
+ // moving stopped, remove handler on next event
+ boolean stop;
+
+ @Override
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
+ if (event.getTypeInt() == Event.ONMOUSEMOVE && !stop
+ && hasMoved(event.getNativeEvent())) {
+ int dx = event.getNativeEvent().getClientX() - startX;
+ int dy = event.getNativeEvent().getClientY() - startY;
+
+ setPopupPosition(startLeft + dx, startTop + dy);
+ event.cancel();
+
+ } else if (event.getTypeInt() == Event.ONMOUSEUP) {
+ stop = true;
+ if (hasMoved(event.getNativeEvent())) {
+ event.cancel();
+ }
+
+ } else if (event.getTypeInt() == Event.ONCLICK) {
+ stop = true;
+ if (hasMoved(event.getNativeEvent())) {
+ event.cancel();
+ }
+
+ } else if (stop) {
+ stop = false;
+ handler.removeHandler();
+ handler = null;
+
+ readPositionAndSize();
+ writeStoredState();
+ }
+ }
+
+ private boolean hasMoved(NativeEvent event) {
+ return Math.abs(startX - event.getClientX()) > MOVE_TRESHOLD
+ || Math.abs(startY - event.getClientY()) > MOVE_TRESHOLD;
+ }
+
+ @Override
+ public void onMouseDown(MouseDownEvent event) {
+ if (handler == null) {
+ handler = Event.addNativePreviewHandler(MoveHandler.this);
+ }
+ startX = event.getClientX();
+ startY = event.getClientY();
+ startLeft = getPopupLeft();
+ startTop = getPopupTop();
+ stop = false;
+ event.preventDefault();
+ }
+
+ }
+
+ /**
+ * Handler for resizing window.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+ protected class ResizeHandler implements MouseDownHandler,
+ MouseMoveHandler, NativePreviewHandler {
+
+ boolean resizeLeft;
+ boolean resizeRight;
+ boolean resizeUp;
+ boolean resizeDown;
+
+ boolean sizing;
+
+ HandlerRegistration dragHandler;
+
+ int startX;
+ int startY;
+ int startW;
+ int startH;
+ int startTop;
+ int startLeft;
+
+ @Override
+ public void onMouseDown(MouseDownEvent event) {
+ sizing = updateResizeFlags(event);
+
+ if (sizing) {
+ startX = event.getClientX();
+ startY = event.getClientY();
+
+ startW = content.getOffsetWidth();
+ startH = content.getOffsetHeight();
+
+ startTop = getPopupTop();
+ startLeft = getPopupLeft();
+
+ dragHandler = Event.addNativePreviewHandler(this);
+
+ event.preventDefault();
+ }
+
+ }
+
+ @Override
+ public void onMouseMove(MouseMoveEvent event) {
+ updateResizeFlags(event);
+ updateCursor();
+ }
+
+ private void updateCursor() {
+ Element c = content.getElement();
+ if (resizeLeft) {
+ if (resizeUp) {
+ c.getStyle().setCursor(Cursor.NW_RESIZE);
+ } else if (resizeDown) {
+ c.getStyle().setCursor(Cursor.SW_RESIZE);
+ } else {
+ c.getStyle().setCursor(Cursor.W_RESIZE);
+ }
+ } else if (resizeRight) {
+ if (resizeUp) {
+ c.getStyle().setCursor(Cursor.NE_RESIZE);
+ } else if (resizeDown) {
+ c.getStyle().setCursor(Cursor.SE_RESIZE);
+ } else {
+ c.getStyle().setCursor(Cursor.E_RESIZE);
+ }
+ } else if (resizeUp) {
+ c.getStyle().setCursor(Cursor.N_RESIZE);
+ } else if (resizeDown) {
+ c.getStyle().setCursor(Cursor.S_RESIZE);
+ } else {
+ c.getStyle().setCursor(Cursor.AUTO);
+ }
+ }
+
+ private boolean updateResizeFlags(MouseEvent event) {
+ Element c = getElement();
+ int w = c.getOffsetWidth();
+ int h = c.getOffsetHeight() - head.getOffsetHeight();
+ int x = event.getRelativeX(c);
+ int y = event.getRelativeY(c) - head.getOffsetHeight();
+
+ resizeLeft = x < HANDLE_SIZE;
+ resizeRight = x > (w - HANDLE_SIZE);
+ resizeUp = y < HANDLE_SIZE;
+ resizeDown = y > (h - HANDLE_SIZE);
+
+ return resizeLeft || resizeRight || resizeUp || resizeDown;
+
+ }
+
+ @Override
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
+ if (event.getTypeInt() == Event.ONMOUSEMOVE) {
+
+ int dx = event.getNativeEvent().getClientX() - startX;
+ int dy = event.getNativeEvent().getClientY() - startY;
+
+ int minw = tabs.getOffsetWidth() + controls.getOffsetWidth();
+ if (resizeLeft) {
+ int w = startW - dx;
+ if (w >= minw) {
+ content.setWidth(w + "px");
+ setPopupPosition(startLeft + dx, getPopupTop());
+ }
+ } else if (resizeRight) {
+ int w = startW + dx;
+ if (w >= minw) {
+ content.setWidth(w + "px");
+ }
+ }
+ if (resizeUp) {
+ int h = startH - dy;
+ if (h >= MIN_HEIGHT) {
+ content.setHeight(h + "px");
+ setPopupPosition(getPopupLeft(), startTop + dy);
+ }
+ } else if (resizeDown) {
+ int h = startH + dy;
+ if (h >= MIN_HEIGHT) {
+ content.setHeight(h + "px");
+ }
+ }
+
+ } else if (event.getTypeInt() == Event.ONMOUSEUP) {
+ dragHandler.removeHandler();
+ dragHandler = null;
+ content.getElement().getStyle().setCursor(Cursor.AUTO);
+ sizing = false;
+ readPositionAndSize();
+ writeStoredState();
+ }
+
+ event.cancel();
+ }
+
+ }
+
+}