Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Initial implementation of file save #16

Merged
merged 22 commits into from
Dec 17, 2011
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
14375eb
Initial implementation of File > Save and dirty bit management
Dec 14, 2011
f048b02
Removed call to temp debug function
Dec 15, 2011
c4493d7
Added comments around our dirty bit management
Dec 15, 2011
8941cd9
Beginning implementation of prompt when closing dirty file
Dec 15, 2011
8b769ba
Merged with latest file read API
Dec 16, 2011
2a3832d
Merge branch 'open-file-from-tree' into save-file
Dec 16, 2011
5701dd6
Merge latest file api and open-file code
Dec 16, 2011
0d169b9
Implementing file close--prompting to save not yet implemented
Dec 16, 2011
33e8cfe
Added dialog when closing dirty file. Refactored dialog code to make …
Dec 16, 2011
72d998c
Made commands rely on $.Deferred() to handle asynchronicity, and upda…
Dec 16, 2011
ef8d96c
Added clarifying comment in FILE_CLOSE command
Dec 16, 2011
b91566c
Trying different indentation style for Deferred callbacks
Dec 16, 2011
8db07b7
Merge branch 'initial-fileio-work' into save-file
Dec 16, 2011
43a0b98
Added another reject() case to doOpen()
Dec 16, 2011
adb37d0
Hooked up to HTML file save API
Dec 16, 2011
3e7c89a
Renamed showDialog() to showModalDialog()
Dec 16, 2011
b01a80b
Refactored brackets.js to make the boot sequence cleaner, and pulled …
Dec 16, 2011
ab3951c
Merge latest save file API
Dec 16, 2011
da5f24d
Merge remote-tracking branch 'origin/initial-fileio-work' into save-file
Dec 16, 2011
b2df1a1
Merge remote-tracking branch 'origin/master' into save-file
Dec 16, 2011
9a91763
Merge remote-tracking branch 'origin/master' into save-file
Dec 17, 2011
dbf5170
Code review cleanup
Dec 17, 2011
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/CommandManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ CommandManager._commands = {};
*
* @param {string} id The ID of the command.
* @param {function} command The function to call when the command is executed. Any arguments passed to
* execute() (after the id) are passed as arguments to the function.
* execute() (after the id) are passed as arguments to the function. If the function is asynchronous,
* it must return a jQuery Deferred that is resolved when the command completes. Otherwise, the
* CommandManager will assume it is synchronous, and return a Deferred that is already resolved.
*/
CommandManager.register = function(id, command) {
if (CommandManager._commands[id]) {
Expand All @@ -24,13 +26,21 @@ CommandManager.register = function(id, command) {
* Runs a global command. Additional arguments are passed to the command.
*
* @param {string} id The ID of the command to run.
* @return {Deferred} a jQuery Deferred that will be resolved when the command completes.
*/
CommandManager.execute = function(id) {
var command = CommandManager._commands[id];
if (command) {
command.apply(null, Array.prototype.slice.call(arguments, 1));
var result = command.apply(null, Array.prototype.slice.call(arguments, 1));
if (result === undefined) {
return $.Deferred().resolve();
}
else {
return result;
}
}
else {
console.log("Attempted to call unregistered command: " + id);
return $.Deferred().reject();
}
}
4 changes: 3 additions & 1 deletion src/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
* List of constants for global command IDs.
*/
var Commands = {
FILE_OPEN: "file.open"
FILE_OPEN: "file.open",
FILE_SAVE: "file.save",
FILE_CLOSE: "file.close"
};
112 changes: 112 additions & 0 deletions src/KeyBindingManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
*/

var KeyBindingManager = {
/**
* The map of all registered keymaps.
*/
_keymaps: {},

/**
* The map of currently active keymaps. As new keymaps come into effect, they are pushed onto the end of
* the array. Later keymaps take precedence over earlier ones.
*/
_activeKeymaps: {},

/**
* The maximum possible keymap level.
*/
_maxLevel: -1,

/**
* Registers the specified keymap based on its id.
*
* TODO: do Closure annotations support user-defined types?
* @param {KeyMap} keymap The keymap to register.
*/
registerKeymap: function(keymap) {
KeyBindingManager._keymaps[keymap.id] = keymap;
if (keymap.level > KeyBindingManager._maxLevel) {
KeyBindingManager._maxLevel = keymap.level;
}
},

/**
* Activate the specified keymap. This installs it at the appropriate level, replacing any other keymap
* at that level.
*
* TODO: does the Closure annotation syntax support user-created types?
* @param {string} keymap The ID of the registered keymap to install.
*/
activateKeymap: function(id) {
var keymap = KeyBindingManager._keymaps[id];
if (!keymap) {
throw new Error("Keymap " + id + " not registered");
}

KeyBindingManager._activeKeymaps[keymap.level] = keymap;
},

/**
* Deactivate the keymap with the given ID. If it's not already active, does nothing.
*
* @param {string} id The ID of the keymap to deactivate.
*/
deactivateKeymap: function(id) {
for (var i = 0; i < KeyBindingManager._maxLevel; i++) {
if (KeyBindingManager._activeKeymaps[i] && KeyBindingManager._activeKeymaps[i].id === id) {
delete KeyBindingManager._activeKeymaps[i];
}
}
},

/**
* Process the keybinding for the current key.
*
* @param {string} A key-description string.
* @return {boolean} true if the key was processed, false otherwise
*/
handleKey: function(key) {
for (var i = KeyBindingManager._maxLevel; i >= 0; i--) {
var keymap = KeyBindingManager._activeKeymaps[i];
if (keymap && keymap.map[key]) {
CommandManager.execute(keymap.map[key]);
return true;
}
}
return false;
}
};

/** class Keymap
*
* A keymap specifies how keys are mapped to commands. The KeyBindingManager allows for a hierarchy of
* keymaps, specified by a numeric level. It does not dictate the semantics of these levels, but in
* practice, level 0 is a global keymap, level 1 is a file-type-specific keymap, and deeper levels can
* be used for more specific contexts. When a new keymap is activated, it replaces any other keymap at
* its same level.
*
* Keys are described by strings of the form "[modifier-modifier-...-]key", where modifier is one of
* Ctrl, Alt, or Shift. If multiple modifiers are specified, they must be specified in that order
* (i.e. "Ctrl-Alt-Shift-P" is legal, "Alt-Ctrl-Shift-P" is not).
* (TODO: the above restriction is to simplify mapping--is it too onerous?)
* -- Ctrl maps to Cmd on Mac. (This means that you can't specifically bind to the Ctrl key on Mac.)
* -- Alt maps to the Option key on Mac.
* -- Letters must be uppercase, but do not require Shift by default. To indicate that Shift must be held
* down, you must specifically include Shift.
*
* @constructor
* @param {string} id A unique ID for this keymap.
* @param {number} level The level of this keymap. Must be an integer >= 0.
* @param {map} map An object mapping key-description strings to command IDs.
*/
var KeyMap = function(id, level, map) {
if (id === undefined || level === undefined || map === undefined) {
throw new Error("All parameters to the KeyMap constructor must be specified");
}

this.id = id;
this.level = level;
this.map = map;
};
Loading