Places:Design Overview: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
No edit summary
Line 1: Line 1:
=== Design Overview ===
= Design Overview =
 
== Note ==
 
Do NOT edit this page unless you are on the Places team. Add your comments to the Discussion page.


== Objectives ==
== Objectives ==


Integrate bookmarks, history and other data sources into a single places view that loads inside a browser tab. Make bookmarking easier. Make it easier to find and organize visited places.
* Extensible Bookmark Providers for customization
* Flexible Query System
* Clean Architecture for ease of code reuse and maintainability


== Design Overview ==
== Front End Architecture ==


Implement the new UI using a MVC approach, using SQLite for the back end, implementing a single nsIController object to handle edits across the multiple views (tree/list, toolbar, bookmarks menu, go menu)
The Front End Architecture utilizes a MVC (model-view-controller) design. This calls for clean separation between each of the three components. The benefits of this approach are improved maintainability, stability and extensability.


<center>http://www.bengoodger.com/software/mb/places/MVC.png</center>
Within the Places code, the Model can be considered to be the SQL tables
and the code that creates them, the query system to access them, and the
simple manipulation pathways provided through services like
nsINavHistoryService and nsINavBookmarksService.


== Details ==
The View is the piece that displays information from the Model in one
way or another. In code, these are menu.xml, toolbar.xml and tree.xml.


= Models =
The Controller is the piece that interprets user actions on a selection
and carries them out - basically linking the Model and the View. In
code, this is controller.js.


Bookmarks and History will be implemented using a collection of SQLite tables:
The extent to which these services are kept independent can be seen in
the following details:
* The Model does not in general deal with presentation.
* The Controller knows of "selection" only as a concept abstract from
the details of the selected View (e.g. a complex tree selection versus a
selected toolbar button or menu item). As far as the Controller is
concerned, the selection is a list of Result Nodes, there are no
View-specific selection ranges, etc.
* The Views know nothing about the functions performed when the user
interacts with their content, since that is instance specific. The Views
implement a View Interface which handle translating their unique
selection characteristics into an agnostic form the Controller can deal
with.


* '''Main URL metadata table''' - A large table containing all URLs that the Places system knows about. Includes all of history and bookmarks, and the key metadata about them (url, title, etc.) Keeping all URLs in a single table will make it easier to better create and rank aggregate search results across all URL types (history, bookmarks, feeds, etc)
The idea is someone can instantiate a View, attach a Controller, and
* '''Bookmarks folder hierarchy table''' - A table that describes the folder hierarchy of Bookmarks
define the behavioral characteristics that suit their use, in very
* '''Annotation metadata table''' - A separate table that holds arbitrary metadata about a given URL. This is to prevent the main table from becoming too wide (every extension that adds a custom annotation property widens the large table for all URLs, even those that do not have annotations).
little code. Examples:


These models all supply applicable add, edit and remove APIs for use by the command controllers, and the appropriate notifications for use by third party applications that wish to observe edits, such as Clobber.
'''Bookmarks Menu'''
* instantiate a Menu View, attached to the top level Browser Bookmarks Menu.
* attach the Controller
* attach a command event listener that handles user clicks in the menu
by loading the associated URL, if any, in a browser tab
* root the View on a Model query result, and tell it to populate itself


= Views =
'''Folder Selector'''
* instantiate a Menu View, attached to a menulist in the Places Search
popup.
* attach the Controller
* attach a command event listener that handles user clicks in the menu
by re-rooting a Tree View elsewhere in the UI
* root the View on a Model query result, and tell it to populate itself.


There are three primary types of view for Places:
As you can see, this careful distinction between each allows us to
rapidly build new user interface components by connecting the same Views
and Controller with different application specific functionality.


* '''Tree/List view''' - in the "Places" pane. Can show flat lists or hierarchical structures. Populated by the Storage Template Builder, or an implementation of the nsITreeView interface.
<center>http://www.bengoodger.com/software/mb/places/MVC.png</center>
* '''Toolbar view''' - in the Browser window. Shows folders as buttons that have dropdown menus. Populated by the Storage Template Builder, or an implementation of the nsIRDFDataSource interface.
* '''Menu view''' - in the Browser window. Shows folders as sub menus. Populated by the Storage Template Builder, or an implementation of the nsIRDFDataSource interface.


Each of these views will implement an Abstract View Interface (AVI) which identifies (at the least) the current selection. In the context of a tree, the current selection is a set of rows, for a toolbar it's the node the context menu was brought up on. --> beng - fill in details!
== Details ==


'''User Interface'''
=== Models ===


The user interface combines these views in various ways. It also presents other pieces of UI like context menus and toolbar buttons and search boxes, which execute queries and perform commands on the selection.
Bookmarks and History will be implemented using a collection of SQLite tables:


= Controller =
XXXbrettw fill in details of tables!


A single command controller that advertises the list of supported commands, enabled commands, and executes commands, based on the state supplied by the AVI. The AVI also uses the API supplied by the various back ends (Places Service, Annotation Service) to perform user edits, additions and removals.
Source code: <code>mozilla/browser/components/places/src</code>


= What it Looks Like =
=== Views ===


Something like this:
There are three primary types of view for Places:  
 
<pre>
+-----------------------------------------------------------------------+
| +----------------------+ Search: [              :^] from: [ date ]  |
| | @ All Bookmarks      | +------------------------------------------+ |
| | @ Bookmarks Bar      | | Name              | Location            | |
| | @ All History        | |--------------------+---------------------+ |
| | @ Feeds              | |                                          | |
| | @ Most Visited      | |                                          | |
| | @ Recently Updated  | |                                          | |
| | @ Bonjour            | |                                          | |
| | @ Folder 1          | |                                          | |
| | @ Folder 2          | |                                          | |
| | @ Folder 3          | |                                          | |
| | @ Folder 4          | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| |                      | |                                          | |
| +----------------------+ +------------------------------------------+ |
| ( + New Folder )          ( @ Options ) ( Save Search... )            |
+-----------------------------------------------------------------------+
</pre>


The left bar is a folders-only view of the root of the Bookmarks namespace. It can contain nested folders if folders nest, in a tree view. Users can drag folders onto it. It also contains some pre-defined virtual folders, like Most Visited and Recently Updated. Some of these folders (like History, Bookmarks, the Toolbar etc) cannot be removed because there is no way for them to be recreated once they are gone. The right side shows a filter UI at the top, and a list/tree view below showing the contents of the selection at left.  
* '''Tree/List view''' - Can show flat lists or hierarchical structures. e.g. the panes in the Places Organizer window.
* '''Toolbar view''' - Shows folders as buttons that have dropdown menus. e.g. the Bookmarks Toolbar in the browser window.
* '''Menu view''' - Shows folders as sub menus. e.g. the Bookmarks Menu in the browser window.  


The filter UI at top is simple, showing a text search field and a calendar widget for date range selection. It should be possible to build more complicated queries based on other metadata by clicking a "more" or "+" button to the right of the query line, which will add a new row with more query options.  
Each of these views implement a Places View interface which provides view-agnostic means for obtaining the current selection and other information. The Views themselves take on no controller-like responsibilities. They are not responsible for handling user clicks and opening links, etc - just presenting a list of places.  


Smart queries can be saved as bookmarks using the Save Search button.
XXXben - fill in details!


Grouping can be performed using a "group by" selector (not shown).
Source code: <code>mozilla/browser/components/places/content/tree|menu|toolbar.xml</code>


To be worked out:
=== Controller ===


* What goes in the Bookmarks Menu? A non-critical detail that can be worked out at the end. Perhaps the contents of the left "Places" bar, plus all the user's bookmarks
The Controller connects the Views to the Model. It is responsible for telling the UI what commands are available, enabled and executing them on the back end services.
* Can the calendar widget be made any more discoverable?


'''Sample Places Bar Idea: Feeds'''
Source code: <code>mozilla/browser/components/places/content/controller.js</code>


A Feed folder that is a query of all URLs that have a "feed" annotation. When selected it shows the feeds in the right pane as folders, using the Feed Handler to load the content. The user can choose to sort the content based on recency, which breaks all the content out of the containing Feed folders and intermingles the individual posts from each feed, effectively creating a Feed aggregator.
== Querying History ==
 
= Displaying Items and Results =


<center>http://www.bengoodger.com/software/mb/places/LifeOfQuery.png</center>
<center>http://www.bengoodger.com/software/mb/places/LifeOfQuery.png</center>
Line 100: Line 98:
To display results in a PlacesView, the following steps are performed:  
To display results in a PlacesView, the following steps are performed:  


'''Query Creation'''
=== Query Creation ===


Any list of items is the result of a query. e.g. the contents of a particular bookmark folder is a request for all URLs with the bookmark flag set that are contained by a named folder. Or all pages in a specific date range. And so on. Queries are represented as strings (which can be Bookmarked - "saved searches" or "virtual folders") containing all the parameters. -->brettw - fill in details!
Any list of items is the result of a query. e.g. the contents of a particular bookmark folder is a request for all URLs with the bookmark flag set that are contained by a named folder. Or all pages in a specific date range. And so on. Queries are represented as strings (which can be Bookmarked - "saved searches" or "virtual folders") containing all the parameters. -->brettw - fill in details!


'''Query Execution'''
=== Query Execution ===


The contents of the query string are deserialized and a series of Query objects are constructed. The query objects are executed.  
The contents of the query string are deserialized and a series of Query objects are constructed. The query objects are executed.  


'''Result Gathering'''
=== Result Gathering ===


The results of the execution are gathered. --> brettw - fill in details! Not all queries produce results in the form of rows from the main URL table. Some produce results dynamically by consulting the contents of a directory on the user's file system (e.g. a new implementation of the old File System Datasource), for example. There are potentially other examples of remote data sources being used to feed data into the places view. Data sources like the Feed handler and the Bonjour listener would work slightly differently however. They would have their own timeout/notification based system by which they would detect new content, and then push URLs/rows into the main URL table whenever there was new data, so that when their containers were opened static content from the last dump is shown.  
The results of the execution are gathered. --> brettw - fill in details! Not all queries produce results in the form of rows from the main URL table. Some produce results dynamically by consulting the contents of a directory on the user's file system (e.g. a new implementation of the old File System Datasource), for example. There are potentially other examples of remote data sources being used to feed data into the places view. Data sources like the Feed handler and the Bonjour listener would work slightly differently however. They would have their own timeout/notification based system by which they would detect new content, and then push URLs/rows into the main URL table whenever there was new data, so that when their containers were opened static content from the last dump is shown.  


'''Result Organization'''
=== Result Organization ===


The results object is passed to a "Grouper" which organizes the results into a hierarchy based on a set of rules specified by the user interface. These rules form a kind of filter, for example: show all bookmarks organized into their appropriate folders; show history from last week, grouped by site; show all URLs matching the string "goats" in a flat, ungrouped list.  
The results object is passed to a "Grouper" which organizes the results into a hierarchy based on a set of rules specified by the user interface. These rules form a kind of filter, for example: show all bookmarks organized into their appropriate folders; show history from last week, grouped by site; show all URLs matching the string "goats" in a flat, ungrouped list.  


'''View Creation'''
=== View Creation ===


The grouped results object is passed to the View implementation which supplies the necessary structure for the user interface.
The grouped results object is passed to the View implementation which supplies the necessary structure for the user interface.


For non-tree views, RDF will be used until such a time as a non-RDF template builder becomes available. HistoryResults can be associated with a Places RDF DataSource that registers the result with a serialization of its queries and options (forming a RDF Resource that can be used to root a piece of UI on the result):
== Other Required Work ==
 
<center>http://www.bengoodger.com/software/mb/places/RDFWrapper.png</center>
 
= Other Required Work =


'''Remote Containers'''
=== Remote Containers ===


The following are some example remote Feed containers. The first two are required.  
The following are some example remote Feed containers. The first two are required.  
Line 135: Line 129:
* '''Address Book URLs Container''' - fill a container with URLs mentioned in the system address book
* '''Address Book URLs Container''' - fill a container with URLs mentioned in the system address book


'''Data Migration'''
=== Data Migration ===


Migrating data from Netscape-bookmarks-file-1, [[Mork]], etc, to the storage format.  
Migrating data from Netscape-bookmarks-file-1, [[Mork]], etc, to the storage format.  


'''Property Editor'''
=== Notification API ===
 
A property editing pane for the view pane that allows users to edit properties on individual URLs. This should be easily overlay-able so that extensions can add editors for their own custom properties that they track using the Annotation Service.
 
'''Notification API'''
 
A notification API for third party applications like Clobber that wish to observe edit operations on the back end.
 
'''Complete Storage Template Builder'''
 
The Storage Template Builder will be used for building UI based on storage statements. There is a patch to allow the template builder to become more generic but it needs review/testing, and the Storage sections of it need to be implemented.
 
'''Migrate Form History'''
 
After History, Form History is the only remaining component in Firefox that uses the [[Mork]] data storage format. It should be migrated to use Storage too.
 
'''Remove Mork'''
 
Once all Firefox dependencies on [[Mork]] have been severed, the [[Mork]] component should no longer be built, to save download size, as we predict building storage will incur a download size increase.
 
= Nice to Have =
 
The following things would be great to have but are not requirements:
 
'''In-Place Edit for Trees'''


It should be possible for users to edit the name and URL and other displayed properties of items in the Places tree view, without having to show another dialog. This is not implemented right now on the tree widget.
A notification API for third party applications like Clobber that wish to observe edit operations on the back end.

Revision as of 19:34, 6 March 2006

Design Overview

Objectives

  • Extensible Bookmark Providers for customization
  • Flexible Query System
  • Clean Architecture for ease of code reuse and maintainability

Front End Architecture

The Front End Architecture utilizes a MVC (model-view-controller) design. This calls for clean separation between each of the three components. The benefits of this approach are improved maintainability, stability and extensability.

Within the Places code, the Model can be considered to be the SQL tables and the code that creates them, the query system to access them, and the simple manipulation pathways provided through services like nsINavHistoryService and nsINavBookmarksService.

The View is the piece that displays information from the Model in one way or another. In code, these are menu.xml, toolbar.xml and tree.xml.

The Controller is the piece that interprets user actions on a selection and carries them out - basically linking the Model and the View. In code, this is controller.js.

The extent to which these services are kept independent can be seen in the following details:

  • The Model does not in general deal with presentation.
  • The Controller knows of "selection" only as a concept abstract from

the details of the selected View (e.g. a complex tree selection versus a selected toolbar button or menu item). As far as the Controller is concerned, the selection is a list of Result Nodes, there are no View-specific selection ranges, etc.

  • The Views know nothing about the functions performed when the user

interacts with their content, since that is instance specific. The Views implement a View Interface which handle translating their unique selection characteristics into an agnostic form the Controller can deal with.

The idea is someone can instantiate a View, attach a Controller, and define the behavioral characteristics that suit their use, in very little code. Examples:

Bookmarks Menu

  • instantiate a Menu View, attached to the top level Browser Bookmarks Menu.
  • attach the Controller
  • attach a command event listener that handles user clicks in the menu

by loading the associated URL, if any, in a browser tab

  • root the View on a Model query result, and tell it to populate itself

Folder Selector

  • instantiate a Menu View, attached to a menulist in the Places Search

popup.

  • attach the Controller
  • attach a command event listener that handles user clicks in the menu

by re-rooting a Tree View elsewhere in the UI

  • root the View on a Model query result, and tell it to populate itself.

As you can see, this careful distinction between each allows us to rapidly build new user interface components by connecting the same Views and Controller with different application specific functionality.

MVC.png

Details

Models

Bookmarks and History will be implemented using a collection of SQLite tables:

XXXbrettw fill in details of tables!

Source code: mozilla/browser/components/places/src

Views

There are three primary types of view for Places:

  • Tree/List view - Can show flat lists or hierarchical structures. e.g. the panes in the Places Organizer window.
  • Toolbar view - Shows folders as buttons that have dropdown menus. e.g. the Bookmarks Toolbar in the browser window.
  • Menu view - Shows folders as sub menus. e.g. the Bookmarks Menu in the browser window.

Each of these views implement a Places View interface which provides view-agnostic means for obtaining the current selection and other information. The Views themselves take on no controller-like responsibilities. They are not responsible for handling user clicks and opening links, etc - just presenting a list of places.

XXXben - fill in details!

Source code: mozilla/browser/components/places/content/tree|menu|toolbar.xml

Controller

The Controller connects the Views to the Model. It is responsible for telling the UI what commands are available, enabled and executing them on the back end services.

Source code: mozilla/browser/components/places/content/controller.js

Querying History

LifeOfQuery.png

To display results in a PlacesView, the following steps are performed:

Query Creation

Any list of items is the result of a query. e.g. the contents of a particular bookmark folder is a request for all URLs with the bookmark flag set that are contained by a named folder. Or all pages in a specific date range. And so on. Queries are represented as strings (which can be Bookmarked - "saved searches" or "virtual folders") containing all the parameters. -->brettw - fill in details!

Query Execution

The contents of the query string are deserialized and a series of Query objects are constructed. The query objects are executed.

Result Gathering

The results of the execution are gathered. --> brettw - fill in details! Not all queries produce results in the form of rows from the main URL table. Some produce results dynamically by consulting the contents of a directory on the user's file system (e.g. a new implementation of the old File System Datasource), for example. There are potentially other examples of remote data sources being used to feed data into the places view. Data sources like the Feed handler and the Bonjour listener would work slightly differently however. They would have their own timeout/notification based system by which they would detect new content, and then push URLs/rows into the main URL table whenever there was new data, so that when their containers were opened static content from the last dump is shown.

Result Organization

The results object is passed to a "Grouper" which organizes the results into a hierarchy based on a set of rules specified by the user interface. These rules form a kind of filter, for example: show all bookmarks organized into their appropriate folders; show history from last week, grouped by site; show all URLs matching the string "goats" in a flat, ungrouped list.

View Creation

The grouped results object is passed to the View implementation which supplies the necessary structure for the user interface.

Other Required Work

Remote Containers

The following are some example remote Feed containers. The first two are required.

  • Feed Container - ping and parse RSS/Atom feeds and fill containers with their posts
  • File System Container - show folders and files from the local hard disk
  • Bonjour Container - fill a container with available network resources discovered by Bonjour Zero-Configuration Networking.
  • Address Book URLs Container - fill a container with URLs mentioned in the system address book

Data Migration

Migrating data from Netscape-bookmarks-file-1, Mork, etc, to the storage format.

Notification API

A notification API for third party applications like Clobber that wish to observe edit operations on the back end.