diff --git a/core/fse--class.js b/core/fse--class.js new file mode 100644 index 00000000..4b8a37de --- /dev/null +++ b/core/fse--class.js @@ -0,0 +1,236 @@ +/* jslint node: true */ +'use strict'; + +var ViewController = require('./view_controller.js').ViewController; +var ansi = require('./ansi_term.js'); +var theme = require('./theme.js'); +var MultiLineEditTextView = require('./multi_line_edit_text_view.js').MultiLineEditTextView; +var Message = require('./message.js'); + +var async = require('async'); +var events = require('events'); +var assert = require('assert'); +var _ = require('lodash'); + +module.exports = FullScreenEditor; + +function FullScreenEditor(options) { + events.EventEmitter.call(this); + + assert(_.isObject(options.client)); + assert(_.isObject(options.art)); + assert(_.isString(options.editorType)); + + var self = this; + + // + // options.client + // options.art{} : name -> artAsset + // options.font : optional + // options.editorMode (view|edit|quote) | (editMenu|) + // + // options.editorType : email | area + + this.client = options.client; + this.art = options.art; + this.font = options.font; + this.editorType = options.editorType; + + this.mciData = {}; + + this.editorMode = 'edit'; // view | edit | editMenu | + + this.getFooterName = function(editorMode) { + editorMode = editorMode || this.editorMode; + return 'footer' + _.capitalize(editorMode); // e.g.. 'footerEditMenu' + }; + + this.getFormId = function(name) { + return { + header : 0, + body : 1, + footerEdit : 2, + footerEditMenu : 3, + footerView : 4, + + help : 50, + }[name]; + }; + + this.redrawFooter = function(options, cb) { + async.waterfall( + [ + function moveToFooterPosition(callback) { + // + // Calculate footer staring position + // + // row = (header height + body height) + // + // Header: mciData.body.height + // Body : We must find this in the config / theme + // + // :TODO: don't hard code this -- allow footer height to be part of theme/etc. + self.client.term.rawWrite(ansi.goto(23, 1)); + callback(null); + }, + function clearFooterArea(callback) { + if(options.clear) { + self.client.term.rawWrite(ansi.reset() + ansi.deleteLine(3)); + } + callback(null); + }, + function displayFooterArt(callback) { + var footerArt = self.art[options.footerName]; + + theme.displayThemedAsset( + footerArt, + self.client, + { font : self.font }, + function displayed(err, artData) { + callback(err, artData); + } + ); + } + ], + function complete(err, artData) { + cb(err, artData); + } + ); + }; + + this.redrawAll = function(options, cb) { + var artComponents = [ 'header', 'body' ]; + var art = self.art; + + self.client.term.rawWrite(ansi.resetScreen()); + + async.series( + [ + function displayHeaderAndBody(callback) { + async.eachSeries( artComponents, function dispArt(n, next) { + theme.displayThemedAsset( + art[n], + self.client, + { font : self.font }, + function displayed(err, artData) { + if(options.initMci) { + self.mciData[n] = artData; + } + next(err); + } + ); + }, function complete(err) { + callback(err); + }); + }, + function displayFooter(callback) { + // we have to treat the footer special + self.redrawFooter( { clear : false, footerName : self.getFooterName() }, function footerDisplayed(err) { + if(self.initMci) { + self.mciData[footerName] = artData; + } + callback(err); + }); + }, + function refreshViews(callback) { + if(options.refreshViews) { + artComponents.push(self.getFooterName()); + + artComponents.forEach(function artComp(n) { + self.viewControllers[n].redrawAll(); + }); + } + callback(null); + } + ], + function complete(err) { + cb(err); + } + ); + }; + + this.createViewsForEmail = function() { + var menuLoadOpts = { callingMenu : self }; + + async.series( + [ + function header(callback) { + menuLoadOpts.formId = self.getFormId('header'); + menuLoadOpts.mciMap = self.mciData.header.mciMap; + + self.addViewController( + 'header', + new ViewController( { client : self.client, formId : menuLoadOpts.formId } ) + ).loadFromMenuConfig(menuLoadOpts, function headerReady(err) { + callback(err); + }); + }, + function body(callback) { + menuLoadOpts.formId = self.getFormId('body'); + menuLoadOpts.mciMap = self.mciData.body.mciMap; + + self.addViewController( + 'body', + new ViewController( { client : self.client, formId : menuLoadOpts.formId } ) + ).loadFromMenuConfig(menuLoadOpts, function bodyReady(err) { + callback(err); + }); + }, + function footer(callback) { + var footerName = self.getFooterName(); + + menuLoadOpts.formId = self.getFormId(footerName); + menuLoadOpts.mciMap = self.mciData[footerName].mciMap; + + self.addViewController( + footerName, + new ViewController( { client : self.client, formId : menuLoadOpts.formId } ) + ).loadFromMenuConfig(menuLoadOpts, function footerReady(err) { + callback(err); + }); + } + ], + function complete(err) { + var bodyView = self.viewControllers.body.getView(1); + //self.updateTextEditMode(bodyView.getTextEditMode()); + //self.updateEditModePosition(bodyView.getEditPosition()); + + //self.viewControllers.body.setFocus(false); + //self.viewControllers.header.switchFocus(1); + + cb(err); + } + ); + }; + +} + +require('util').inherits(FullScreenEditor, events.EventEmitter); + +FullScreenEditor.prototype.enter = function() { + + var self = this; + + async.series( + [ + function drawScreen(callback) { + self.redrawAll( { initMci : true }, function allDrawn(err) { + callback(err); + }); + }, + function createViews(callback) { + var createViewsFor = 'createViewsFor' + _.capitalize(self.editorType); // e.g. 'createViewsForEmail' + self[createViewsFor](function viewsCreated(err) { + callback(err); + }); + } + ], + function complete(err) { + self.emit('error', err); + } + ); +}; + +FullScreenEditor.prototype.leave = function() { + +}; diff --git a/mods/menu.json b/mods/menu.json index 7e05b0a6..ec56a709 100644 --- a/mods/menu.json +++ b/mods/menu.json @@ -2,6 +2,10 @@ /* Menu Configuration + Tip: demjson's jsonlint is an excellent tool for linting JSON files + that contains comments: + jsonlint -S menu.json + Some concept/ideas: "mci" : { "BT1" : { @@ -236,7 +240,7 @@ }, { "value" : { "command" : "M" }, - "action" : "@menu:messageAreaMenu" + "action" : "@menu:messageArea" }, { "value" : 1, @@ -247,6 +251,32 @@ /////////////////////////////////////////////////////////////////////// // Message Area Related /////////////////////////////////////////////////////////////////////// + "messageArea" : { + "module" : "msg_area", + "art" : "MSGAREA", + "options" : { "cls" : true }, + "prompt" : "menuCommand", + "submit" : [ + { + "value" : { "command" : "N" }, + "action" : "@menu:messageAreaNewPost" + } + ] + }, + "messageAreaNewPost" : { + "module" : "msg_area_post", + "options" : { "cls" : true }, + "config" : { + "fseArt" : { + "header" : "demo_fse_netmail_header.ans", + "body" : "demo_fse_netmail_body.ans", + "footerEdit" : "demo_fse_netmail_footer_edit.ans", + "footerEditMenu" : "demo_fse_netmail_footer_edit_menu.ans", + "footerView" : "demo_fse_netmail_footer_view.ans", + "help" : "demo_fse_netmail_help.ans" + } + } + }, "messageAreaMenu" : { "module" : "message_area", "art" : "MSGAREA", @@ -273,36 +303,6 @@ } ] }, - "messageAreaNewFSE" : { - "module" : "fse", - "options" : { "cls" : true }, - "config" : { - "editorType" : "area", - "art" : { - "header" : "fse_area_header", - "body" : "fse_area_body", - "footerEdit" : "fse_footer_edit", - "footerEditMenu" : "fse_footer_edit_menu", - "help" : "fse_help" - } - } - } - /*"messageAreaEmailFSE" : { - "module" : "fse", - "options" : { "cls" : true }, - "config" : { - "editorType" : "email", - "art" : { - "header" : "fse_email_header", - "body" : "fse_email_body", - "footerEdit" : "fse_email_footer_edit", - "footerEditMenu" : "fse_email_footer_edit_menu", - "footerView" : "fse_email_footer_view", - "help" : "fse_help" - } - } - }, - */ /////////////////////////////////////////////////////////////////////// // Doors /////////////////////////////////////////////////////////////////////// diff --git a/mods/msg_area.js b/mods/msg_area.js new file mode 100644 index 00000000..d88a16e1 --- /dev/null +++ b/mods/msg_area.js @@ -0,0 +1,36 @@ +/* jslint node: true */ +'use strict'; + +var MenuModule = require('../core/menu_module.js').MenuModule; +//var theme = require('../core/theme.js'); + +//var async = require('async'); +//var assert = require('assert'); +//var _ = require('lodash'); + +exports.getModule = MessageAreaModule; + +exports.moduleInfo = { + name : 'Message Area', + desc : 'Module for interacting with area messages', + author : 'NuSkooler', +}; + +function MessageAreaModule(options) { + MenuModule.call(this, options); + + var self = this; + + this.menuMethods = { + changeArea : function(formData, extraArgs) { + + } + }; +} + +require('util').inherits(MessageAreaModule, MenuModule); + +MessageAreaModule.prototype.mciReady = function(mciData, cb) { + this.standardMCIReadyHandler(mciData, cb); +}; + diff --git a/mods/msg_area_post.js b/mods/msg_area_post.js new file mode 100644 index 00000000..d5b348e2 --- /dev/null +++ b/mods/msg_area_post.js @@ -0,0 +1,50 @@ +/* jslint node: true */ +'use strict'; + +var MenuModule = require('../core/menu_module.js').MenuModule; +var FullScreenEditor = require('../core/fse--class.js'); // :TODO: fix this +//var theme = require('../core/theme.js'); + +var async = require('async'); +var assert = require('assert'); +var _ = require('lodash'); + +exports.getModule = MessageAreaPostModule; + +exports.moduleInfo = { + name : 'Message Area Post', + desc : 'Module posting a new message to an area', + author : 'NuSkooler', +}; + +function MessageAreaPostModule(options) { + MenuModule.call(this, options); + + var self = this; + + + this.initSequence = function() { + var fse = new FullScreenEditor( { + client : this.client, + art : this.menuConfig.config.fseArt, + font : this.menuConfig.font, + editorType : 'area', + editorMode : 'edit', + }); + + fse.on('error', function fseError(err) { + + }); + + fse.enter(); + }; +} + +require('util').inherits(MessageAreaPostModule, MenuModule); + +/* +MessageAreaPostModule.prototype.mciReady = function(mciData, cb) { + this.standardMCIReadyHandler(mciData, cb); +}; +*/ +