Metacortex

From ApocryphWiki

Jump to: navigation, search

Contents

Metacortex

Tuesday, August 21, 2007 10:17 PM


I'm fairly sure one of the many problems I'm having formalizing this idea is that I currently wish for maybe half a dozen different tools, so the confusion starts when I mix them up. It's as if I need the functionality of 'ps', 'grep', 'diff', and 'rsync', and keep blending the requirements together.

What are some of my requirements?

  • Blogging interface that's more like a notebook and less like a CMS.

○ Easy ad-hoc multimedia posts ○ Easy links between posts. ○ Ability to use blog as place to keep notes for myself that are actually usable by me

  • Note-taking tool that can accommodate arbitrary structure. Todo items, appointments, contacts, minutes, diagrams, free-form notes, all in the same workspace
  • Quicksilver-like system to easily find stuff, choose verbs, and fire!
  • Tool to suck in a list of bugs (say, bugs assigned to a milestone), move them around physically as a way of grouping, in-place edit parameters like assignee, close bugs, resolve them, create new ones, mark them up with arbitrary metadata
  • Library of bits of information I want to keep around, like clippings of Ruby syntax
  • Keep track of todo items
  • Keep my bookmarks in a system I control instead of Furl

Blue-sky features that would be cool

  • Markup tool I can use to suck in documents (web page, word doc, pdf, source code, whatever) and mark it up.
  • Integration with email, so email is sucked into the information universe
  • Ability to implement GTD system entirely in one tool
  • Ability to sync repositories between instances
  • Shared workspaces with multiple real-time contributors
  • Integration with contact managers and calendars for the same reason
  • Integration with IM tools to suck IM conversations into the universe
  • Getting info into the system is as easy as getting it out. IMAP server shows the email, iCal the calendar entries, vCards for contacts, WebDAV for files
  • Auto-discovery of other instances on LANs, and IP-based communication with any instance. Authentication by OpenID. Easy sharing of objects, push and pull
  • An environment for simple computation as well, ala Mathematica's notebook idiom
  • An environment which could be simply described as a smart, persistent, infinite whiteboard. All sorts of structured and unstructured info can be entered and manipulated. Spreadsheets, UML models, architecture diagrams, schedules, etc. Easy to enter using a standard keyboard (maybe with chording based on the home row for advanced users) and easy to share in a machine-readable form.


Small tools loosely coupled

Tuesday, August 21, 2007 10:50 PM

Given the sheer scope of this problem, it cries out for small, easy to grok tools that tie together.

Obviously some of the tasks must be accomplished by monolithic software. A notetaking app can't be built with just grep, awk, and pipes! Nonetheless, a Quicksilver-like subject/verb[/object] tool could be the glue, combined with a sufficiently flexible data storage solution and a lightweight data bus for interconnectivity.

Let's take just the note taking (or blogging) app for a moment. If that's built of little tools, it would be under the covers of a larger user-facing tool, if for no other reason than to provide a GUI.

Implementation

Saturday, August 25, 2007 2:17 PM

I'm trying a small-scale iterative implementation based on WPF, trying to get something usable as soon as possible.

Things a tool would need before I could switch to it in lieu of OneNote:

  • Basic rich text formatting, including bold, italics, underline, bulleted and numbered lists, and tables
  • Save and retrieve notes in some sort of built-in hierarchy like OneNote
  • Automatic saving, like OneNote

That's obviously multiple iterations of work. I've decided to focus first on the basic rich text formatting, as I think it'll be a relatively easy intro to WPF. The RichTextEdit control already does the formatting I need, it just needs some GUI plumbing.

Also, conveniently, the native format of the RichTextEdit doc tree is a XAML FlowDocument. I already have code working in a test harness to keep a real-time pretty-printed XML version of the whole doc tree. That makes persistence a no-brainer, which really helps. There's also a few samples around the 'net for XAML<->HTML conversion, which will be handy for the blog posting feature later on.

Future ideas:

  • The OneNote 2k7 API is much improved. It seems quite possible now to import notebooks from OneNote into another tool. That would be very important for me since I have a lot invested in OneNote already
  • Blog posting interface, to post and update notebook pages to a blog engine API
  • All the fancy MetaCortex Grand Unified Theory stuff

Iteration 1

Saturday, August 25, 2007 5:32 PM

Requirements for this iteration:

  • Rich text editor with basic rich text primitives:

○ Bold ○ Italics ○ Underline ○ Bulleted list ○ Numbered list ○ Undo/Redo ○ Copy/Cut/Paste

  • Toolbar with the above commands

Seems simple enough, but it turns out there's one major gotcha. The much-vaunted WPF Command functionality in point of fact sucks balls.

The idea is that a bunch of Command objects are defined (static mostly), and various input elements implement various commands. RichTextBox implements all of the EditingCommands commands, plus the ApplicationCommands. So, if you send it EditingCommands.ToggleBold, it will toggle bold on the currently selected text. Since you can create toolbar buttons bound to commands sent to a specific command target with nothing but XAML, the samples would lead you to believe that your work is done.

However, that's only if you don't care about the state of the toolbar buttons. In every word processor since (at least) Word 6.0, if the cursor is in some text that's bold, the big 'B' toolbar button looks pressed, otherwise it's not. In other words, it's a toggle. Unfortunately, the balls-to-the-wall WPF Command framework doesn't have a facility for representing this sort of state (just enabled or not enabled).

The end result is that I have to handle any event that might change the location of the cursor in the rich text box (in practice, SelectionChanged seems to do it), then for each of the toggleable toolbar buttons, I have to update their state based on my educated guess of the state of the selected text.


On an unrelated note, I was using the VS2k5 image library for the toolbar icons, but it turns out there's an SDK sample "Create a RichTextBox with a Toolbar", that includes almost all of the icons I want, including a few missing from the image library. Sweet. Unfortunately they're 24x24 icons, while the ones from the image library ar 16x16. Bugger

I figured out how to detect when a range of text is contained by a List object, but in testing it I've discovered a problem with the way the RichTextBox works. Assume you've got a complex document, and you select text that includes plain text, bold text, and half of a bulleted list. By convention, the 'bulleted list' toolbar button should be pressed to show you've got some list items, and pressing it again will clear the list attribute from the two list items and leave the rest of the selection alone. Instead, sending the ToggleBullets command when the selection includes mixed list and non-list text, nothing happens! I'm afraid I'll have to override the ToggleBullets command. Great.

Here are the selection/command requirements:

Selection Contains Command State Result Unbolded text Bold Up Text is bolded Bold text Bold Down Text is unbolded Unitalic text Italic Up Text is italic Italic text Italic Down Text is unitaliced Non-underlined text Underline Up Text is underlined Underlined text Underline Down Text is non-underlined Bold and unbolded text Bold Up Text is unbolded Italic and unitalic text Italic Up Text is unitaliced Underlined and non-underlined text Underline Up Text is non-underlined Unbulleted text Bullets Up Text is bulleted Bulleted text Bullets Down Text us unbulleted Bulleted and unbulleted text Bullets Up All selected text is bulleted Unnumbered text Numbered Up Text is numbered Numbered text Numbered Down Text is unnumbered Numbered and unnumbered text Numbered Up All selected text is numbered

Right now, the bold and italic stuff works correctly. The underline logic isn't ever detecting the selected text is underlined, so that's broken. The bulleted and numbered lists stuff also aren't working right. I'd also like to see things like the Undo button greyed out if RichTextBox.CanUndo is false, and same for redo. Decrease indent should be disabled if the text is all the way left.

Also, if text is aligned left, you click align right, the text is right aligned and the 'Align Right' button goes down, but the 'Align Left' button stays down as well. When one of these commands is executed, the button status should update.

Having though about this overnight, I think I'll have to embed the RichTextBox in a custom control of my own devising, which will pass most commands right through to the RTB, but will process some (like bullets and numbering) my own way. It will also disable commands that are not available, like undo when there's nothing to undo, paste when there's nothing on the clipboard, etc.

I've come up with a neat way to succinctly write pass-through command handlers, but there's another problem. It seems when my toolbar buttons are images (as they almost all are), when the command they represent cannot be executed (eg, Copy when there's nothing selected), clicking the button does nothing, and it doesn't react to mouseover, but it also isn't greyed out. WTF?

Issues this iteration: Name Desc Status TOOLBAR_GRAY Toolbar buttons corresponding to non-executable commands are not greyed out Resolved LIST_HANDLING The behavior of the bullet and number list buttons isn't consistent with the requirements Open UNDO_ENABLE The Undo command should be disabled is RichTextBox.CanUndo is false. Ditto the redo command and CanRedo Resolved DECREASE_INDENT_ENABLE The Decrease Indent command should be disabled if the cursor/selection is already against the left margin Resolved


Note to future self: There's an issue embedding UI controls into FlowDocument objects within a RichTextBox. The issue is they are disabled. A possible workaround is at http://learnwpf.com/Posts/Post.aspx?postId=4cd7884c-2e1b-4699-8206-8321c59f4cc0 . If that doesn't work I'm well and truly fucked. Another reference to this issue is http://www.charlespetzold.com/blog/2006/01/180334.html

Another note to self: You can easily extract the WPF definition of a control with Expression Blend by choosing to edit a copy of its template. Using this technique, I figured out why buttons with images in them don't gray the image; the only thing that changes when a button goes to disabled is the foreground color goes to gray. Yeah. Lame.

I've spent an hour researching TOOLBAR_GRAY, and I've got nothing. I can't believe this is such a pain in the ass. Sure, I can make a button that contains a spinning alpha-blended video file with just a few lines of XAML, but when I want to reproduce a feature like grayed-out toolbar buttons (which, incidentally, MFC did automatically way back in 1995), I'm screwed to the wall. How the FUCK did we get to this point?

Regarding bug DECREASE_INDENT_ENABLE, it seems this will be a crufty feature. Based on my test harness looking at the XAML produced by the RTB, when you first 'increase indent' on a paragraph, it sets the left margin to "20". Increase it again, it leaves the margin at 20 and sets "Text Indent" to 20, for a total of 40. Indent again, and margin changes to 40 for a total of 60. Every indent after that adds 20 to the margin.

The interesting thing about TextIndent vs Margin is that TextIndent applies only to the first line of the paragraph, while Margin applies to the whole thing. When increasing indent, it seems that past the first increase, TextIndent will be set to 20 for the indent if it was previously 0, otherwise the margin is bumped. When decreasing indent, TextIndent is dropped to zero, and only if that's zero does the margin decrease.

For my purposes, all I have to do is detect whether or not the text is indented. The heuristic is clearly to look through all paragraphs in the selected range, and check for non-zero margin or non-zero text indent; either of those is a yes.

Regarding TOOLBAR_GRAY, I've come up with XAML that will generate a grayscale version of an image, but it's not pretty, and I have NFI how to incorporate it into a Button style to make it work automatically. A post at http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=737933&SiteID=1 gave me the idea, but it took some fiddling to get it to work in pure XAML (it doesn't help that Expression Blend doesn't render the resulting image correctly, making it seem that the grayscale image is blank when it renders fine in IE)

I found another workaroudn to TOOLBAR_GRAY, which blows harder but is also more workable. At http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1691587&SiteID=1 it's suggested that you can make the image more transparent as a way to make it seem faded out. Triggers make this easy, and I was able to incorporate it as a style with little fuss. The result isn't quite what I wanted, since the resulting images still have color, but it provides enough of a visual cue to get the job done for now.

Personal tools