Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}
h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}
.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}
.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}
.tabSelected{color:[[ColorPalette::PrimaryDark]];
background:[[ColorPalette::TertiaryPale]];
border-left:1px solid [[ColorPalette::TertiaryLight]];
border-top:1px solid [[ColorPalette::TertiaryLight]];
border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}
#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}
.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}
#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}
.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}
.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}
.tiddler .defaultCommand {font-weight:bold;}
.shadow .title {color:[[ColorPalette::TertiaryDark]];}
.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}
.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}
.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}
.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}
.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}
.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}
.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}
.imageLink, #displayArea .imageLink {background:transparent;}
.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}
.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}
.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}
.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}
.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}
.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}
body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}
h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}
hr {height:1px;}
a {text-decoration:none;}
dt {font-weight:bold;}
ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}
.txtOptionInput {width:11em;}
#contentWrapper .chkOptionInput {border:0;}
.externalLink {text-decoration:underline;}
.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}
.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}
/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}
#mainMenu .tiddlyLinkExisting,
#mainMenu .tiddlyLinkNonExisting,
#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}
.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}
.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}
#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}
#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}
.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}
#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}
.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}
.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}
.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}
#contentWrapper {display:block;}
#splashScreen {display:none;}
#displayArea {margin:1em 17em 0 14em;}
.toolbar {text-align:right; font-size:.9em;}
.tiddler {padding:1em 1em 0;}
.missing .viewer,.missing .title {font-style:italic;}
.title {font-size:1.6em; font-weight:bold;}
.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}
.tiddler .button {padding:0.2em 0.4em;}
.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}
.footer {font-size:.9em;}
.footer li {display:inline;}
.annotation {padding:0.5em; margin:0.5em;}
* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}
.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}
.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}
.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}
.fieldsetFix {border:0; padding:0; margin:1px 0px;}
.sparkline {line-height:1em;}
.sparktick {outline:0;}
.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}
* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}
.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser
Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])
<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]
----
Also see [[AdvancedOptions]]
Updated XBAP sample application ([[link|http://mstlab.org/xbap/d3/DynamicDataDisplay.Xbap.Samples.xbap]]) - now it contains samples with new markers, too:
[img[Images/Markers-in-xbap-app.png]]
Introducing new settings of ~DateTimeAxis: two ~DependencyProperties: ''~MayorLabelBackgroundBrush'' and ''~MayorLabelRectangleBorderProperty''.
These properties affects on rendering of ~DateTimeAxis's mayor tick labels, for example, the following code:
{{{
<d3:ChartPlotter Name="plotter">
<d3:ChartPlotter.MainHorizontalAxis>
<d3:HorizontalDateTimeAxis MayorLabelBackgroundBrush="AliceBlue" MayorLabelRectangleBorderProperty="DarkBlue"/>
</d3:ChartPlotter.MainHorizontalAxis>
</d3:ChartPlotter>
}}}
gives the following result:
[img[Images/DateTimeAxisMayorLabelProperties.png]]
ChartPlotter is a control that contains everything connected to charting in DynamicDataDisplay, and that is why your almost every usage of DynamicDataDisplay will begin from creating an instance of this class.
ChartPlotter is a non-abstract descendant class of [[Plotter2D]], and [[Plotter2D]] is a descendant of [[Plotter]] class.
ChartPlotter by default contains a series of elements:
* Horizontal and vertical axes
* ~AxisGrid - a series of horizontal and vertical lines across visible chart area, starting at axes ticks
* two [[AxisNavigation]]s for horizontal and vertical axes
* [[Legend]] control for displaying a list of chart descriptions
* KeyboardNavigation - element which contains several implementations of frequently-used commands, and keyboard binding for them, such as arrows for panning chart, '-' and '+' for zooming chart, etc
* MouseNavigation - element which allows to pan and zoom charts using mouse
* DefaultContextMenu - plotter's context menu with some pre-added commands, and ability to add user commands, too.
ChartPlotter has a series of properties, that allows to get an instance of such added-by-default chart: these are ChartPlotter.~MouseNavigation, ChartPlotter.~KeyboardNavigation and similar.
To add a new element to plotter, execute the following code:
{{{
plotter.Children.Add(chart);
}}}
You can delete any of built-in elements or elements, added by your code, and this will cause disappearing of functionality provided by removed element. To remove any element from Plotter, execute the following code:
{{{
plotter.Children.Remove(chart);
}}}
where ''chart'' is an element you want to remove from ''plotter''.
This is a plotter element that adds to parent ChartPlotter context menu with several built-in commands:
* Fit plotter's content to view
* Save screenshot of plotter's content
* Copy screenshot to clipboard
* Display brief help
* Send feedback about DynamicDataDisplay's controls
We had to create this plotter element instead of usual adding our ~MenuItems to plotter's ~ContextMenu, because in the common case plotter's menu would not open if click was made on some content over plotter instead of plotter itself.
[[DynamicDataDisplay]]
[[ChartPlotter]]
DynamicDataDisplay is a name of a library of charting components for Windows Presentation Foundation and .NET, written in C#, and hosted at [[dynamicdatadisplay.codeplex.com|http://dynamicdatadisplay.codeplex.com]]
Often the name of this component is shortened to ''D3'' by the first letters of its full name.
DynamicDataDisplay is created in the Laboratory of Microsoft technologies in Moscow State University, in Moscow, Russia.
Default namespace of DynamicDataDisplay is ''Microsoft.Research.~DynamicDataDisplay'', and there is also a set of sub-namespaces like ''Microsoft.Research.~DynamicDataDisplay.Charts'', and others. The most part of these namespaces is mapped to one //xml namespace//: "http://research.microsoft.com/DynamicDataDisplay/1.0", so adding this namespace to your XAML file fill allow you to create all DynamicDataDisplay classes in XAML.
Useful DynamicDataDisplay's links:
* Main site - [[http://DynamicDataDisplay.codeplex.com|http://DynamicDataDisplay.codeplex.com]]
* D3's twit - [[http://twitter.com/DynamicDataDisp|http://twitter.com/DynamicDataDisp]]
* XBAP Samples application - [[http://mstlab.org/xbap/d3/DynamicDataDisplay.Xbap.Samples.xbap|http://mstlab.org/xbap/d3/DynamicDataDisplay.Xbap.Samples.xbap]] (proper look in Microsoft IE)
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
Test
If you need to make two [[CursorCoordinateGraphs|CursorCoordinateGraph]] of two [[ChartPlotters|ChartPlotter]], you need to perform two steps:
# Set ~AutoHide property of each CursorCoordinateGraph. This will prevent elements from hiding when mouse leaves associated plotter.
# Set a binding on Position property:
{{{
leftCursor.SetBinding(CursorCoordinateGraph.PositionProperty, new Binding
{
Source = rightCursor,
Path = new PropertyPath("Position"),
Mode = BindingMode.TwoWay
});
}}}
where //leftCursor// and //rightCursor// are both [[CursorCoordinateGraphs|CursorCoordinateGraph]] of two [[ChartPlotters|ChartPlotter]].
To synchronize visible areas of two [[ChartPlotters|ChartPlotter]], use the following binding:
{{{
plotter1.Viewport.SetBinding(Viewport2D.VisibleProperty, new Binding("Visible"){Source=plotter2.Viewport, Mode=BindingMode.TwoWay});
}}}
This is working because [[Viewport|Viewport2D]]'s Visible property is a dependency property.
~IPlotterElement is a .NET interface, containing 3 main members:
* method ''~OnPlotterAttached([[Plotter]] plotter)'', which is called by Plotter when element is being added to its Children collection
* method ''~OnPlotterDetaching([[Plotter]] plotter)'', which is called by Plotter when element is being removed from this Plotter's Children collection
* property ''[[Plotter]] Plotter { get; }'', which should return parent Plotter, when element is added to some Plotter, or null, when it is not added
Every element, that wants to be added to Plotter (and therefore to its Children collection) should implement this interface. Here is a basic and the simplest implementation of it:
{{{
class SomeChart : IPlotterElement {
void IPlotterElement.OnPlotterAttached(Plotter plotter) {
this.plotter = plotter;
}
void IPlotterElement.OnPlotterDetaching(Plotter plotter) {
this.plotter = null;
}
private Plotter plotter;
Plotter Plotter {
get{ return this.plotter; }
}
}
}}}
! ~OnPlotterAttached method
This method, as it is written above, is called by parent Plotter when an instance of class, implementing [[IPlotterElement|IPlotterElement interface]] interface, is being added to it. In this method Plotter, passed in parameter 'plotter', can be saved to a field of class, to use it after attaching to Plotter. Also you can add some visual element to [[plotter's layout panels|Plotter layout panels]], or subscribe to some events of Plotter itself or its other parts, e.g. other charts.
before calling this method, Plotter checks that the value, returned by ''Plotter'' property, is null, and after calling this method, Plotter checks that this value equals to this Plotter. If some of this conditions is wrong, Plotter throws an exception, so one chart can be added only to one Plotter at one time.
! ~OnPlotterDetaching method
This method is opposite to ~OnPlotterAttached method, and its purpose is to allow the chart to remove from Plotter's visual tree all visual elements, added by this chart previously, and to unsubscribe from all events, connected to Plotter or its parts and other charts. After calling this method on element being removed, Plotter assures that value returned by ''Plotter'' property, is null, otherwise it throws an exception.
KeyboardNavigation, being added to [[Plotter]], adds to it bindings to some commands of ''~ChartCommands'' static class.
Basic keyboard shortcuts of ChartPlotter:
|!Shortcut|!Command|
|Arrow keys|Panning charts|
|'-' (minus key)|Zoom out|
|'+' (plus key, but without any modifier like Shift or Ctrl, so actually this is '=' key)|Zoom in|
|Ctrl+S|Save screenshot of ChartPlotter to file, shows ~OpenFileDialog|
|F11|Copy screenshot of ChartPlotter to clipboard|
|Home|Modifies visible area so that all charts becomes visible|
|F1|Show brief help|
''F1'' key shows help window like this:
[img[Images/AboutWindow.png]]
//Note//: You can press buttons in this window and this cause corresponding action to be performed.
[[DynamicDataDisplay]]
[[ChartPlotter]]
[[Blog posts|#tag:journal]]
Mikhail is me, one of DynamicDataDisplay developers.
That is how I'm looking like:
[img[Images\Mikhail.jpg]]
Basic mouse actions of ChartPlotter:
|!Mouse action|!Command|
|Click of LMB (//left mouse button//)|Moves focus to plotter|
|Click of RMB|Shows plotters's [[context menu|DefaultContextMenu]]|
|Double click of LMB|Zoom in|
|Double click of RMB|Zoom out|
|Mouse wheel|Zoom in or out|
|Ctrl+LMB pressed and then moved|Select an area to zoom in and the perform zoom in|
|Shift+LMB pressed and then moved|Select an area to zoom in with the same aspect ratio as visible area has, and then perform zoom in|
[[Plotter]] class is a abstract base class for [[Plotter2D]], and has 2 main roles:
# It has a property ''Children'', which is a collection of elements, implementing interface [[IPlotterElement|IPlotterElement interface]]. When you want something to be added to Plotter, you need to add an instance of this something to this collection.
# It contains several [[panels|Plotter layout panels]], which form layout of elements inside of Plotter.
By default, Plotter has some built-in panels which form its visual tree. This visual tree is described in Common/~PlotterStyle.xaml file, and looks nearly like this:
[img[Images/PlotterPanels.png]]
To create such image, I've used the following XAML:
{{{
<d3:ChartPlotter>
<d3:Header>HeaderPanel</d3:Header>
<d3:HorizontalAxis Placement="Top"/>
<d3:VerticalAxis Placement="Right"/>
<d3:HorizontalAxisTitle Placement="Bottom">BottomPanel</d3:HorizontalAxisTitle>
<d3:HorizontalAxisTitle Placement="Top">TopPanel</d3:HorizontalAxisTitle>
<d3:VerticalAxisTitle Placement="Left">LeftPanel</d3:VerticalAxisTitle>
<d3:VerticalAxisTitle Placement="Right">RightPanel</d3:VerticalAxisTitle>
<d3:Footer>FooterPanel</d3:Footer>
</d3:ChartPlotter>
}}}
which filled up Plotter with necessary elements, and I've also changed a little [[Plotter]]'s Template, to display labels for ~CentralGrid and ~MainCanvas.
As you can see from this picture, Plotter has following main panels:
* ~HeaderPanel
* ~MainGrid
** ~LeftPanel
** ~RightPanel
** ~TopPanel
** ~BottomPanel
** ~CentralGrid
** ~MainCanvas
* ~FooterPanel
These panels has different purpose - ''~HeaderPanel'' and ''~FooterPanel'' are holding chart's ''Header'' and ''Footer'', ''~LeftPanel'', ''~RightPanel'', ''~TopPanel'' and ''~BottomPanel'' generally contains [[axes|Axes]], titles for these axes and controls for changing visible area only in the direction of the respective axes, called ''AxisNavigation''. ''~CentralGrid'' and ''~MainCanvas'' generally contains charts and other auxiliary controls.
[[Plotter2D]] class is an abstract base class for ChartPlotter. [[Plotter2D]]'s base class is [[Plotter]].
The main feature of [[Plotter2D]] is that it has a [[Viewport|Viewport2D]] - a means for coordinate transforming, which is very important in charting.
[[Plotter2D]] also exposes some properties and methods of its [[Viewport|Viewport2D]] so that they were accessible from XAML.
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal "DD MMM YYYY" "journal">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel "options ยป" "Change TiddlyWiki advanced options">>
http://microsoft.cs.msu.su/personal/thecentury/Public%20Documents/Wiki/D3.html
[[Viewport2D]] belongs to a set classes that composes coordinate transfomation mechanism in DynamicDataDisplay.
The most important properties of Viewport2D are:
* ~DataRect ''Visible'' { get; set; } - a rectangle of visible area in so called ''viewport'' coordinates. This is a dependency property.
* Rect ''Output'' { get; } - a screen rectangle. Usually this is a rectangle like { X=0, Y=0, Width=value, Height=value }.
* CoordinateTransform ''Transform'' { get; set; } - gets or sets a value of class that is capable to transform points from different coordinate systems of DynamicDataDisplay. This is a immutable class, meaning that you can safely store some CoordinateTransform and neither of its properties will change.
By default, [[Viewport|Viewport2D]] is in ''~FitToView'' mode - this means that content bounds of those charts that have some non-default value set to Viewport2D.~ContentBounds attached dependency property will be united, and Viewport's actual Visible area will contain this union of content bounds. When content bounds of any chart changes, Viewport2D will update its visible area to contain new updated bounds. When user pans or zooms the visible area, or when programmatically Viewport2D.Visible changes by setting any value to it, this mode switches off, and Viewport no longer tracks changes of charts' content bounds. To switch Viewport to ''~FitToView'' mode, user can select ''Fit to view'' command in ChartPlotter's [[context menu|DefaultContextMenu]], or programmer can write the following code: {{{plotter.FitToView();}}}
! Coordinate systems of DynamicDataDisplay
There are three coordinate systems in D3:
Data <-> Viewport <-> Screen
* Screen is a coordinate system of screen. This coordinate system is provided by WPF, its unit is WPF's //device independent pixel//, its vertical axis goes from top to bottom of screen, so point with coordinates (0,0) is in the left top corner of screen. Example of rectangle in screen coordinates: new Rect(X~~0~~=0 px, y~~0~~=0 px, Width=640 px, Height=480 px)
* Viewport is a coordinate system between data and screen coordinates. Its vertical axis goes from bottom to top, so point (0,0) is in the left bottom corner. Example of rectangle in viewport coordinates: new DataRect(X~~min~~=0, Y~~min~~=0, X~~max~~=1, Y~~max~~=1).
* Data is a coordinate system of actual data. It can be usual Cartesian coordinate system, it can be polar, or have one or both logarithmic axes.
Transform between Viewport and Screen coordinate systems is built in into CoordinateTransform, and cannot be changed. It simply maps points between ~ViewportRect and ~ScreenRect of CoordinateTransform. When user pans or zooms charts, Visible rectangle of Viewport2D changes, and this writes new value to Viewport2D.CoordinateTransform property.
Transform between Data and Viewport coordinate systems can be changed, for example, by setting a new value to Plotter2D.DataTransform or by executing the following code: {{{ viewport.Transform = viewport.Transform.WithDataTransform(value); }}}
! ~ViewportRestrictions
[[ViewportRestriction]]s are a way to coerce the value of Viewport2D.Visible property somehow.
ViewportRestriction is a way to somehow influence on Viewport2D.Visible property coercion.
In C#-words, ViewportRestriction is a subclass of ViewportRestriction with overridden ''Apply'' method:
{{{
public abstract DataRect Apply(DataRect previousDataRect, DataRect proposedDataRect, Viewport2D viewport);
}}}
What does ViewportRestriction allow to archive:
* restrict horizontal or vertical movements of visible area
* apply a custom trajectory to visible area movement
* limit minimal or maximal values of visible area (minimal and maximal zoom)
* make visible area always have the same proportions that its screen image has
* implement different data-tracking scenarios, such as following the latest added data point, limiting width of visible area to some value, implementing by this a sliding window for data watch
[[ViewportRestriction]]s can be added into two different collections of Viewport2D: ''Restrictions'' and ''~FitToViewRestrictions''. Restrictions, added to the first collection, are being applied every time Viewport2D.Visible's value changes.
Restrictions, added to ~FitToViewRestrictions, are being applied only when [[Viewport|Viewport2D]] is in ''~FitToView'' mode.
Viewport2D's Domain property, which is a maximal value of visible area, is also implemented through [[restrictions|ViewportRestriction]].