/** * @preserve * Silex, live web creation * http://projects.silexlabs.org/?/silex/ * * Copyright (c) 2012 Silex Labs * http://www.silexlabs.org/ * * Silex is available under the GPL license * http://www.silexlabs.org/silex/silex-licensing/ */ /** * @fileoverview This file defines the entry point of Silex * * a view holds a reference to the controllers so that it can order changes on * the models a controller holds a reference to the models so that it can change * them a model holds a reference to the views so that it can update them * */ import { detect } from 'detect-browser'; import { Config } from './ClientConfig'; import { ContextMenuController } from './controller/context-menu-controller'; import { CssEditorController } from './controller/css-editor-controller'; import { EditMenuController } from './controller/edit-menu-controller'; import { FileMenuController } from './controller/file-menu-controller'; import { HtmlEditorController } from './controller/html-editor-controller'; import { InsertMenuController } from './controller/insert-menu-controller'; import { JsEditorController } from './controller/js-editor-controller'; import { PageToolController } from './controller/page-tool-controller'; import { PropertyToolController } from './controller/property-tool-controller'; import { SettingsDialogController } from './controller/settings-dialog-controller'; import { StageController } from './controller/stage-controller'; import { TextEditorController } from './controller/text-editor-controller'; import { ToolMenuController } from './controller/tool-menu-controller'; import { ViewMenuController } from './controller/view-menu-controller'; import { Body } from './model/body'; import { Component } from './model/Component'; import { SilexElement } from './model/element'; import { File } from './model/file'; import { Head } from './model/head'; import { Page } from './model/page'; import { Property } from './model/property'; import { Controller, Model, View } from './types'; import { SilexNotification } from './utils/notification'; import { BreadCrumbs } from './view/bread-crumbs'; import { ContextMenu } from './view/context-menu'; import { CssEditor } from './view/dialog/css-editor'; import { Dashboard } from './view/dialog/Dashboard'; import { FileExplorer } from './view/dialog/file-explorer'; import { HtmlEditor } from './view/dialog/html-editor'; import { JsEditor } from './view/dialog/js-editor'; import { SettingsDialog } from './view/dialog/settings-dialog'; import { Menu } from './view/menu'; import { PageTool } from './view/page-tool'; import { PropertyTool } from './view/property-tool'; import { Splitter } from './view/splitter'; import { StageWrapper } from './view/StageWrapper'; import { TextFormatBar } from './view/TextFormatBar'; import { getUiElements } from './view/UiElements'; import { Workspace } from './view/workspace'; /** * Defines the entry point of Silex client application * */ export class App { /** * store the model instances * the model instances are passed to the controllers and the views */ model: Model; /** * store the view instances * the view instaces have access to the models and controllers */ view: View; /** * store the controller instances * controller instances have access to the views and the models */ controller: Controller; /** * Entry point of Silex client application * create all views and models and controllers * */ constructor(debug= false) { // the debug flag comes from index.jade or debug.jade Config.debug.debugMode = debug; if (Config.debug.debugMode) { console.warn('Silex starting in debug mode.'); } // empty objects, to pass references to each other and later populate them const emptyModel: Model = { file: null, head: null, body: null, page: null, element: null, component: null, property: null, }; const emptyController: Controller = { fileMenuController: null, editMenuController: null, viewMenuController: null, insertMenuController: null, toolMenuController: null, contextMenuController: null, stageController: null, pageToolController: null, propertyToolController: null, settingsDialogController: null, htmlEditorController: null, cssEditorController: null, jsEditorController: null, textEditorController: null, }; const emptyView: View = { menu: null, contextMenu: null, breadCrumbs: null, pageTool: null, propertyTool: null, textFormatBar: null, htmlEditor: null, cssEditor: null, jsEditor: null, fileExplorer: null, settingsDialog: null, dashboard: null, propSplitter: null, workspace: null, stageWrapper: null, }; // create all the components of Silex app this.model = this.initModel(emptyView, emptyController, emptyModel); this.controller = this.initController(emptyView, emptyController, emptyModel); this.view = this.initView(emptyView, emptyController, emptyModel); // init views now that controllers and model are instanciated this.view.workspace.buildUi(); this.view.menu.buildUi(); this.view.contextMenu.buildUi(); this.view.breadCrumbs.buildUi(); this.view.pageTool.buildUi(); this.view.dashboard.buildUi(); this.view.propertyTool.buildUi(); // warning when not ff or chrome const browser = detect(); const isFirefox = browser && browser.name === 'firefox'; const isChrome = browser && browser.name === 'chrome'; if (!isFirefox && !isChrome) { SilexNotification.alert('Warning', ` Your browser is not supported yet.

Considere using Firefox or chrome.

Note: I believe you use ${ browser ? browser.name : 'Unknown' } `, () => {}); } // the build type if (!Config.debug.debugMode) { // warning small screen size // height must be enough to view the settings pannel // width is just arbitrary const winSizeWidth = document.documentElement.clientWidth; const winSizeHeight = document.documentElement.clientHeight; const minWinSizeWidth = 950; const minWinSizeHeight = 630; if (winSizeHeight < minWinSizeHeight || winSizeWidth < minWinSizeWidth) { SilexNotification.alert('Warning', `Your window is very small (${winSizeWidth}x${ winSizeHeight}) and Silex may not display correctly.

Considere maximizing the window or use a bigger screen to use Silex at its best. A window size of ${ minWinSizeWidth}x${ minWinSizeHeight} is considered to be a acceptable.`, () => {}); } } // draw the workspace once this.view.workspace.redraw(this.view); // application start, open a new empty file this.controller.fileMenuController.newFile( () => { this.view.workspace.loadingDone(); this.initDebug(); }, () => { this.view.workspace.loadingDone(); this.initDebug(); }); } initDebug() { if (Config.debug.debugMode && Config.debug.debugScript) { const script = document.createElement('script'); script.type = 'text/javascript'; script.src = Config.debug.debugScript; document.body.appendChild(script); } // prevent accidental unload if (!Config.debug.debugMode || Config.debug.preventQuit) { this.view.workspace.startWatchingUnload(); } } /** * creation of the view instances */ initView(emptyView, emptyController, emptyModel) { const uiElements = getUiElements(); // Stage const stageWrapper = new StageWrapper(uiElements.stage, emptyModel, emptyController); // Menu const menu = new Menu(uiElements.menu, emptyModel, emptyController); // context menu const contextMenu = new ContextMenu(uiElements.contextMenu, emptyModel, emptyController); // bread crumbs const breadCrumbs = new BreadCrumbs(uiElements.breadCrumbs, emptyModel, emptyController); // PageTool const pageTool = new PageTool(uiElements.pageTool, emptyModel, emptyController); // HtmlEditor const htmlEditor = new HtmlEditor(uiElements.htmlEditor, emptyModel, emptyController); // CssEditor const cssEditor = new CssEditor(uiElements.cssEditor, emptyModel, emptyController); // JsEditor const jsEditor = new JsEditor(uiElements.jsEditor, emptyModel, emptyController); // SettingsDialog const settingsDialog = new SettingsDialog(uiElements.settingsDialog, emptyModel, emptyController); // Dashboard const dashboard = new Dashboard(uiElements.dashboard, emptyModel, emptyController); // FileExplorer const fileExplorer = new FileExplorer(uiElements.fileExplorer, emptyModel, emptyController); // PropertyTool const propertyTool = new PropertyTool(uiElements.propertyTool, emptyModel, emptyController); // TextFormatBar const textFormatBar = new TextFormatBar(uiElements.textFormatBar, emptyModel, emptyController); // workspace const workspace = new Workspace(uiElements.workspace, emptyModel, emptyController); // add splitters const propSplitter = new Splitter(uiElements.verticalSplitter, emptyModel, emptyController, () => workspace.resizeProperties()); propSplitter.addLeft(uiElements.contextMenu); propSplitter.addLeft(uiElements.breadCrumbs); propSplitter.addLeft(uiElements.stage.parentElement); propSplitter.addRight(uiElements.propertyTool); // init the view class which references all the views emptyView.menu = menu; emptyView.contextMenu = contextMenu; emptyView.breadCrumbs = breadCrumbs; emptyView.pageTool = pageTool; emptyView.propertyTool = propertyTool; emptyView.textFormatBar = textFormatBar; emptyView.htmlEditor = htmlEditor; emptyView.cssEditor = cssEditor; emptyView.jsEditor = jsEditor; emptyView.fileExplorer = fileExplorer; emptyView.settingsDialog = settingsDialog; emptyView.dashboard = dashboard; emptyView.propSplitter = propSplitter; emptyView.workspace = workspace; emptyView.stageWrapper = stageWrapper; emptyView.uiElements = uiElements; return emptyView; } /** * creation of the model classes * create the models to be passed to the controllers and the views */ initModel(emptyView, emptyController, emptyModel) { // init the model class which references all the views emptyModel.file = new File(emptyModel, emptyView); emptyModel.head = new Head(emptyModel, emptyView); emptyModel.body = new Body(emptyModel, emptyView); emptyModel.page = new Page(emptyModel, emptyView); emptyModel.element = new SilexElement(emptyModel, emptyView); emptyModel.component = new Component(emptyModel, emptyView); emptyModel.property = new Property(emptyModel, emptyView); return emptyModel; } /** * init the controller class with references to the views and the models */ initController(emptyView, emptyController, emptyModel) { emptyController.fileMenuController = new FileMenuController(emptyModel, emptyView); emptyController.editMenuController = new EditMenuController(emptyModel, emptyView); emptyController.viewMenuController = new ViewMenuController(emptyModel, emptyView); emptyController.insertMenuController = new InsertMenuController(emptyModel, emptyView); emptyController.toolMenuController = new ToolMenuController(emptyModel, emptyView); emptyController.contextMenuController = new ContextMenuController(emptyModel, emptyView); emptyController.stageController = new StageController(emptyModel, emptyView); emptyController.pageToolController = new PageToolController(emptyModel, emptyView); emptyController.propertyToolController = new PropertyToolController(emptyModel, emptyView); emptyController.settingsDialogController = new SettingsDialogController(emptyModel, emptyView); emptyController.htmlEditorController = new HtmlEditorController(emptyModel, emptyView); emptyController.cssEditorController = new CssEditorController(emptyModel, emptyView); emptyController.jsEditorController = new JsEditorController(emptyModel, emptyView); emptyController.textEditorController = new TextEditorController(emptyModel, emptyView); return emptyController; } } // tslint:disable:no-string-literal window['silex'] = new App();