<commit_before>'use strict';

function draw_logic(){
    for(var vertex in vertices){
        canvas_draw_path({
          'style': 'stroke',
          'vertices': [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertex]['dy'],
            },
            {
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
        });
        canvas_draw_path({
          'style': 'stroke',
          'vertices': [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
            {
              'x': vertices[vertices[vertex]['parent']]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
        });
    }

    // Draw vertices_amount and lineWidth.
    canvas_buffer.fillText(
      vertices_amount,
      0,
      25
    );
    canvas_buffer.fillText(
      canvas_buffer.lineWidth,
      0,
      50
    );
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] = math_clamp({
          'max': 360,
          'min': 0,
          'value': vertices[vertex]['loop'] + vertices[vertex]['speed'],
          'wrap': true,
        });

        var rotation = vertices[vertex]['loop'] * math_degree;

        vertices[vertex]['dx'] =
          canvas_x
          + vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(rotation);
        vertices[vertex]['dy'] =
          canvas_y
          + vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(rotation);
    }
}

function randomize(){
    vertices.length = 0;

    var loop_counter = vertices_amount - 1;
    do{
        vertices.push({
          'dx': 0,
          'dy': 0,
          'loop': core_random_integer({
            'max': 360,
          }),
          'parent': vertices_amount - loop_counter,
          'radius': Math.random() * properties['radius'] + 5,
          'speed': core_random_integer({
            'max': properties['speed'],
          }) - properties['speed'] / 2,
          'x': core_random_integer({
            'max': properties['x'],
          }) - properties['x'] / 2,
          'y': core_random_integer({
            'max': properties['y'],
          }) - properties['y'] / 2,
        });
    }while(loop_counter--);

    vertices[vertices_amount - 1]['parent'] = 0;
}

function repo_init(){
    core_repo_init({
      'title': '9YG0E6r.htm',
    });
    core_events_bind({
      'keybinds': {
        65: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth = Math.max(
                canvas_buffer.lineWidth - 1,
                1
              );
          },
        },
        68: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth += 1;
          },
        },
        83: {
          'todo': function(){
              vertices_amount = Math.max(
                vertices_amount - 1,
                2
              );
              randomize();
          },
        },
        87: {
          'todo': function(){
              vertices_amount += 1;
              randomize();
          },
        },
        'all': {
          'todo': randomize,
        },
      },
      'mousebinds': {
        'mousedown': {
          'todo': randomize,
        },
      },
    });
    canvas_init();
}

function resize_logic(){
    canvas_buffer.fillStyle = '#fff';
    canvas_buffer.lineJoin = 'round';
    canvas_buffer.strokeStyle = '#fff';

    randomize();
}

var properties = {
  'radius': 20,
  'speed': 15,
  'x': 500,
  'y': 500,
};
var vertices = [];
var vertices_amount = 23;
<commit_msg>added keybinds/mousebinds args to core_repo_init()<commit_after>'use strict';

function draw_logic(){
    for(var vertex in vertices){
        canvas_draw_path({
          'style': 'stroke',
          'vertices': [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertex]['dy'],
            },
            {
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
        });
        canvas_draw_path({
          'style': 'stroke',
          'vertices': [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
            {
              'x': vertices[vertices[vertex]['parent']]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
        });
    }

    // Draw vertices_amount and lineWidth.
    canvas_buffer.fillText(
      vertices_amount,
      0,
      25
    );
    canvas_buffer.fillText(
      canvas_buffer.lineWidth,
      0,
      50
    );
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] = math_clamp({
          'max': 360,
          'min': 0,
          'value': vertices[vertex]['loop'] + vertices[vertex]['speed'],
          'wrap': true,
        });

        var rotation = vertices[vertex]['loop'] * math_degree;

        vertices[vertex]['dx'] =
          canvas_x
          + vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(rotation);
        vertices[vertex]['dy'] =
          canvas_y
          + vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(rotation);
    }
}

function randomize(){
    vertices.length = 0;

    var loop_counter = vertices_amount - 1;
    do{
        vertices.push({
          'dx': 0,
          'dy': 0,
          'loop': core_random_integer({
            'max': 360,
          }),
          'parent': vertices_amount - loop_counter,
          'radius': Math.random() * properties['radius'] + 5,
          'speed': core_random_integer({
            'max': properties['speed'],
          }) - properties['speed'] / 2,
          'x': core_random_integer({
            'max': properties['x'],
          }) - properties['x'] / 2,
          'y': core_random_integer({
            'max': properties['y'],
          }) - properties['y'] / 2,
        });
    }while(loop_counter--);

    vertices[vertices_amount - 1]['parent'] = 0;
}

function repo_init(){
    core_repo_init({
      'keybinds': {
        65: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth = Math.max(
                canvas_buffer.lineWidth - 1,
                1
              );
          },
        },
        68: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth += 1;
          },
        },
        83: {
          'todo': function(){
              vertices_amount = Math.max(
                vertices_amount - 1,
                2
              );
              randomize();
          },
        },
        87: {
          'todo': function(){
              vertices_amount += 1;
              randomize();
          },
        },
        'all': {
          'todo': randomize,
        },
      },
      'mousebinds': {
        'mousedown': {
          'todo': randomize,
        },
      },
      'title': '9YG0E6r.htm',
    });
    canvas_init();
}

function resize_logic(){
    canvas_buffer.fillStyle = '#fff';
    canvas_buffer.lineJoin = 'round';
    canvas_buffer.strokeStyle = '#fff';

    randomize();
}

var properties = {
  'radius': 20,
  'speed': 15,
  'x': 500,
  'y': 500,
};
var vertices = [];
var vertices_amount = 23;
<|endoftext|>


<commit_before>// # The Ghost Boot Sequence

// IMPORTANT: The only global requires here should be debug + overrides
const debug = require('ghost-ignition').debug('boot');
require('./server/overrides');
// END OF GLOBAL REQUIRES

const initCore = async ({ghostServer}) => {
    const settings = require('./server/services/settings');
    const jobService = require('./server/services/jobs');
    const models = require('./server/models');
    const {events, i18n} = require('./server/lib/common');

    ghostServer.registerCleanupTask(async () => {
        await jobService.shutdown();
    });

    // Initialize Ghost core internationalization
    i18n.init();
    debug('Default i18n done for core');

    models.init();
    debug('Models done');

    await settings.init();

    // @TODO: fix this - has to happen before db.ready is emitted
    debug('Begin: Url Service');
    require('./frontend/services/url');
    debug('End: Url Service');

    // @TODO: fix this location
    events.emit('db.ready');
};

const initExpressApps = async () => {
    debug('Begin: initExpressApps');
    const themeService = require('./frontend/services/themes');
    const frontendSettings = require('./frontend/services/settings');

    await frontendSettings.init();
    debug('Frontend settings done');

    await themeService.init();
    debug('Themes done');

    const parentApp = require('./server/web/parent/app')();

    debug('End: initExpressApps');
    return parentApp;
};

const initServices = async ({config}) => {
    debug('Begin: initialiseServices');
    const themeService = require('./frontend/services/themes');
    const frontendSettings = require('./frontend/services/settings');
    const appService = require('./frontend/services/apps');
    const urlUtils = require('./shared/url-utils');

    // CASE: When Ghost is ready with bootstrapping (db migrations etc.), we can trigger the router creation.
    //       Reason is that the routers access the routes.yaml, which shouldn't and doesn't have to be validated to
    //       start Ghost in maintenance mode.
    // Routing is a bridge between the frontend and API
    const routing = require('./frontend/services/routing');
    // We pass the themeService API version here, so that the frontend services are less tightly-coupled
    routing.bootstrap.start(themeService.getApiVersion());

    const settings = require('./server/services/settings');
    const permissions = require('./server/services/permissions');
    const xmlrpc = require('./server/services/xmlrpc');
    const slack = require('./server/services/slack');
    const {mega} = require('./server/services/mega');
    const webhooks = require('./server/services/webhooks');
    const scheduling = require('./server/adapters/scheduling');
    const getRoutesHash = () => frontendSettings.getCurrentHash('routes');

    await Promise.all([
        // Initialize the permissions actions and objects
        permissions.init(),
        xmlrpc.listen(),
        slack.listen(),
        mega.listen(),
        webhooks.listen(),
        settings.syncRoutesHash(getRoutesHash),
        appService.init(),
        scheduling.init({
            // NOTE: When changing API version need to consider how to migrate custom scheduling adapters
            //       that rely on URL to lookup persisted scheduled records (jobs, etc.). Ref: https://github.com/TryGhost/Ghost/pull/10726#issuecomment-489557162
            apiUrl: urlUtils.urlFor('api', {version: 'v3', versionType: 'admin'}, true)
        })
    ]);

    debug('XMLRPC, Slack, MEGA, Webhooks, Scheduling, Permissions done');

    // Initialise analytics events
    if (config.get('segment:key')) {
        require('./analytics-events').init();
    }

    debug('End: initialiseServices');
};

const mountGhost = (rootApp, ghostApp) => {
    const urlService = require('./frontend/services/url');
    rootApp.disable('maintenance');
    rootApp.use(urlService.utils.getSubdir(), ghostApp);
};

const bootGhost = async () => {
    // Metrics & debugging
    const startTime = Date.now();
    let ghostServer;

    try {
        // Config is the absolute first thing to do!
        debug('Begin: Load config');
        const config = require('./shared/config');
        debug('End: Load config');

        debug('Begin: Load version info');
        const version = require('./server/lib/ghost-version');
        config.set('version', version);
        debug('End: Load version info');

        debug('Begin: load server + minimal app');
        process.env.NODE_ENV = process.env.NODE_ENV || 'development';

        // Get minimal application in maintenance mode
        const rootApp = require('./app');

        // Start server with minimal App
        const GhostServer = require('./server/ghost-server');
        ghostServer = new GhostServer();
        await ghostServer.start(rootApp);

        const logging = require('./shared/logging');
        logging.info('Ghost server start', (Date.now() - startTime) / 1000 + 's');
        debug('End: load server + minimal app');

        debug('Begin: Get DB ready');
        // Get the DB ready
        await require('./db').ready();
        debug('End: Get DB ready');

        // Load Ghost with all its services
        debug('Begin: Load Ghost Core Services');
        await initCore({ghostServer});

        const ghostApp = await initExpressApps({});
        await initServices({config});
        debug('End: Load Ghost Core Services');

        // Mount the full Ghost app onto the minimal root app & disable maintenance mode
        mountGhost(rootApp, ghostApp);

        // Announce Server Readiness
        logging.info('Ghost boot', (Date.now() - startTime) / 1000 + 's');
        GhostServer.announceServerReadiness();
    } catch (error) {
        const errors = require('@tryghost/errors');
        // @TODO: fix these extra requires
        const GhostServer = require('./server/ghost-server');
        const logging = require('./shared/logging');

        let serverStartError = error;

        if (!errors.utils.isIgnitionError(serverStartError)) {
            serverStartError = new errors.GhostError({message: serverStartError.message, err: serverStartError});
        }

        logging.error(serverStartError);
        GhostServer.announceServerReadiness(serverStartError);

        if (ghostServer) {
            ghostServer.shutdown(2);
        } else {
            setTimeout(() => {
                process.exit(2);
            }, 100);
        }
    }
};

module.exports = bootGhost;
<commit_msg>Fixed path to analytics-events in boot file<commit_after>// # The Ghost Boot Sequence

// IMPORTANT: The only global requires here should be debug + overrides
const debug = require('ghost-ignition').debug('boot');
require('./server/overrides');
// END OF GLOBAL REQUIRES

const initCore = async ({ghostServer}) => {
    const settings = require('./server/services/settings');
    const jobService = require('./server/services/jobs');
    const models = require('./server/models');
    const {events, i18n} = require('./server/lib/common');

    ghostServer.registerCleanupTask(async () => {
        await jobService.shutdown();
    });

    // Initialize Ghost core internationalization
    i18n.init();
    debug('Default i18n done for core');

    models.init();
    debug('Models done');

    await settings.init();

    // @TODO: fix this - has to happen before db.ready is emitted
    debug('Begin: Url Service');
    require('./frontend/services/url');
    debug('End: Url Service');

    // @TODO: fix this location
    events.emit('db.ready');
};

const initExpressApps = async () => {
    debug('Begin: initExpressApps');
    const themeService = require('./frontend/services/themes');
    const frontendSettings = require('./frontend/services/settings');

    await frontendSettings.init();
    debug('Frontend settings done');

    await themeService.init();
    debug('Themes done');

    const parentApp = require('./server/web/parent/app')();

    debug('End: initExpressApps');
    return parentApp;
};

const initServices = async ({config}) => {
    debug('Begin: initialiseServices');
    const themeService = require('./frontend/services/themes');
    const frontendSettings = require('./frontend/services/settings');
    const appService = require('./frontend/services/apps');
    const urlUtils = require('./shared/url-utils');

    // CASE: When Ghost is ready with bootstrapping (db migrations etc.), we can trigger the router creation.
    //       Reason is that the routers access the routes.yaml, which shouldn't and doesn't have to be validated to
    //       start Ghost in maintenance mode.
    // Routing is a bridge between the frontend and API
    const routing = require('./frontend/services/routing');
    // We pass the themeService API version here, so that the frontend services are less tightly-coupled
    routing.bootstrap.start(themeService.getApiVersion());

    const settings = require('./server/services/settings');
    const permissions = require('./server/services/permissions');
    const xmlrpc = require('./server/services/xmlrpc');
    const slack = require('./server/services/slack');
    const {mega} = require('./server/services/mega');
    const webhooks = require('./server/services/webhooks');
    const scheduling = require('./server/adapters/scheduling');
    const getRoutesHash = () => frontendSettings.getCurrentHash('routes');

    await Promise.all([
        // Initialize the permissions actions and objects
        permissions.init(),
        xmlrpc.listen(),
        slack.listen(),
        mega.listen(),
        webhooks.listen(),
        settings.syncRoutesHash(getRoutesHash),
        appService.init(),
        scheduling.init({
            // NOTE: When changing API version need to consider how to migrate custom scheduling adapters
            //       that rely on URL to lookup persisted scheduled records (jobs, etc.). Ref: https://github.com/TryGhost/Ghost/pull/10726#issuecomment-489557162
            apiUrl: urlUtils.urlFor('api', {version: 'v3', versionType: 'admin'}, true)
        })
    ]);

    debug('XMLRPC, Slack, MEGA, Webhooks, Scheduling, Permissions done');

    // Initialise analytics events
    if (config.get('segment:key')) {
        require('./server/analytics-events').init();
    }

    debug('End: initialiseServices');
};

const mountGhost = (rootApp, ghostApp) => {
    const urlService = require('./frontend/services/url');
    rootApp.disable('maintenance');
    rootApp.use(urlService.utils.getSubdir(), ghostApp);
};

const bootGhost = async () => {
    // Metrics & debugging
    const startTime = Date.now();
    let ghostServer;

    try {
        // Config is the absolute first thing to do!
        debug('Begin: Load config');
        const config = require('./shared/config');
        debug('End: Load config');

        debug('Begin: Load version info');
        const version = require('./server/lib/ghost-version');
        config.set('version', version);
        debug('End: Load version info');

        debug('Begin: load server + minimal app');
        process.env.NODE_ENV = process.env.NODE_ENV || 'development';

        // Get minimal application in maintenance mode
        const rootApp = require('./app');

        // Start server with minimal App
        const GhostServer = require('./server/ghost-server');
        ghostServer = new GhostServer();
        await ghostServer.start(rootApp);

        const logging = require('./shared/logging');
        logging.info('Ghost server start', (Date.now() - startTime) / 1000 + 's');
        debug('End: load server + minimal app');

        debug('Begin: Get DB ready');
        // Get the DB ready
        await require('./db').ready();
        debug('End: Get DB ready');

        // Load Ghost with all its services
        debug('Begin: Load Ghost Core Services');
        await initCore({ghostServer});

        const ghostApp = await initExpressApps({});
        await initServices({config});
        debug('End: Load Ghost Core Services');

        // Mount the full Ghost app onto the minimal root app & disable maintenance mode
        mountGhost(rootApp, ghostApp);

        // Announce Server Readiness
        logging.info('Ghost boot', (Date.now() - startTime) / 1000 + 's');
        GhostServer.announceServerReadiness();
    } catch (error) {
        const errors = require('@tryghost/errors');
        // @TODO: fix these extra requires
        const GhostServer = require('./server/ghost-server');
        const logging = require('./shared/logging');

        let serverStartError = error;

        if (!errors.utils.isIgnitionError(serverStartError)) {
            serverStartError = new errors.GhostError({message: serverStartError.message, err: serverStartError});
        }

        logging.error(serverStartError);
        GhostServer.announceServerReadiness(serverStartError);

        if (ghostServer) {
            ghostServer.shutdown(2);
        } else {
            setTimeout(() => {
                process.exit(2);
            }, 100);
        }
    }
};

module.exports = bootGhost;
<|endoftext|>


<commit_before>'use strict';

function draw_logic(){
    for(var vertex in vertices){
        canvas_draw_path({
          'style': 'stroke',
          'vertices': [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertex]['dy'],
            },
            {
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
            {
              'x': vertices[vertices[vertex]['parent']]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
        });
    }

    // Draw vertices_amount and lineWidth.
    canvas_buffer.fillText(
      vertices_amount,
      0,
      25
    );
    canvas_buffer.fillText(
      canvas_buffer.lineWidth,
      0,
      50
    );
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] += vertices[vertex]['speed'];
        if(vertices[vertex]['loop'] > 359){
            vertices[vertex]['loop'] -= 360;

        }else if(vertices[vertex]['loop'] < 0){
            vertices[vertex]['loop'] += 360;
        }

        var rotation = vertices[vertex]['loop'] * math_degree;

        vertices[vertex]['dx'] =
          canvas_x
          + vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(rotation);
        vertices[vertex]['dy'] =
          canvas_y
          + vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(rotation);
    }
}

function randomize(){
    vertices.length = 0;

    var loop_counter = vertices_amount - 1;
    do{
        vertices.push({
          'dx': 0,
          'dy': 0,
          'loop': core_random_integer({
            'max': 360,
          }),
          'parent': vertices_amount - loop_counter,
          'radius': Math.random() * properties['radius'] + 5,
          'speed': core_random_integer({
            'max': properties['speed'],
          }) - properties['speed'] / 2,
          'x': core_random_integer({
            'max': properties['x'],
          }) - properties['x'] / 2,
          'y': core_random_integer({
            'max': properties['y'],
          }) - properties['y'] / 2,
        });
    }while(loop_counter--);

    vertices[vertices_amount - 1]['parent'] = 0;
}

function repo_init(){
    canvas_init();
    core_input_binds_add({
      'keybinds': {
        27: {
          'todo': function(){
              canvas_buffer.lineWidth = 1;
              if(vertices_amount !== 23){
                vertices_amount = 23;
                randomize();
              }
          },
        },
        65: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth = Math.max(
                canvas_buffer.lineWidth - 1,
                1
              );
          },
        },
        68: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth += 1;
          },
        },
        83: {
          'todo': function(){
              vertices_amount = Math.max(
                vertices_amount - 1,
                2
              );
              randomize();
          },
        },
        87: {
          'todo': function(){
              vertices_amount += 1;
              randomize();
          },
        },
        'all': {
          'todo': randomize,
        },
      },
      'mousebinds': {
        'mousedown': {
          'todo': randomize,
        },
      },
    });
}

function resize_logic(){
    canvas_buffer.fillStyle = '#fff';
    canvas_buffer.lineJoin = 'round';
    canvas_buffer.strokeStyle = '#fff';

    randomize();
}

var properties = {
  'radius': 20,
  'speed': 15,
  'x': 500,
  'y': 500,
};
var vertices = [];
var vertices_amount = 23;
<commit_msg>reverted canvas_draw_path() change, added math_clamp() usage<commit_after>'use strict';

function draw_logic(){
    for(var vertex in vertices){
        canvas_draw_path({
          'style': 'stroke',
          'vertices': [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertex]['dy'],
            },
            {
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
        });
        canvas_draw_path({
          'style': 'stroke',
          'vertices': [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
            {
              'x': vertices[vertices[vertex]['parent']]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
        });
    }

    // Draw vertices_amount and lineWidth.
    canvas_buffer.fillText(
      vertices_amount,
      0,
      25
    );
    canvas_buffer.fillText(
      canvas_buffer.lineWidth,
      0,
      50
    );
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] = math_clamp({
          'max': 360,
          'min': 0,
          'value': vertices[vertex]['loop'] + vertices[vertex]['speed'],
          'wrap': true,
        });

        var rotation = vertices[vertex]['loop'] * math_degree;

        vertices[vertex]['dx'] =
          canvas_x
          + vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(rotation);
        vertices[vertex]['dy'] =
          canvas_y
          + vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(rotation);
    }
}

function randomize(){
    vertices.length = 0;

    var loop_counter = vertices_amount - 1;
    do{
        vertices.push({
          'dx': 0,
          'dy': 0,
          'loop': core_random_integer({
            'max': 360,
          }),
          'parent': vertices_amount - loop_counter,
          'radius': Math.random() * properties['radius'] + 5,
          'speed': core_random_integer({
            'max': properties['speed'],
          }) - properties['speed'] / 2,
          'x': core_random_integer({
            'max': properties['x'],
          }) - properties['x'] / 2,
          'y': core_random_integer({
            'max': properties['y'],
          }) - properties['y'] / 2,
        });
    }while(loop_counter--);

    vertices[vertices_amount - 1]['parent'] = 0;
}

function repo_init(){
    canvas_init();
    core_input_binds_add({
      'keybinds': {
        27: {
          'todo': function(){
              canvas_buffer.lineWidth = 1;
              if(vertices_amount !== 23){
                vertices_amount = 23;
                randomize();
              }
          },
        },
        65: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth = Math.max(
                canvas_buffer.lineWidth - 1,
                1
              );
          },
        },
        68: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth += 1;
          },
        },
        83: {
          'todo': function(){
              vertices_amount = Math.max(
                vertices_amount - 1,
                2
              );
              randomize();
          },
        },
        87: {
          'todo': function(){
              vertices_amount += 1;
              randomize();
          },
        },
        'all': {
          'todo': randomize,
        },
      },
      'mousebinds': {
        'mousedown': {
          'todo': randomize,
        },
      },
    });
}

function resize_logic(){
    canvas_buffer.fillStyle = '#fff';
    canvas_buffer.lineJoin = 'round';
    canvas_buffer.strokeStyle = '#fff';

    randomize();
}

var properties = {
  'radius': 20,
  'speed': 15,
  'x': 500,
  'y': 500,
};
var vertices = [];
var vertices_amount = 23;
<|endoftext|>


<commit_before>/*
 * Windows Native Settings Handler
 *
 * Deals with individual settings that are only accessible throught isolated
 * API calls.
 *
 * Copyright 2018 Raising the Floor - International
 *
 * Licensed under the New BSD license. You may not use this file except in
 * compliance with this License.
 *
 * The research leading to these results has received funding from the European Union's
 * Seventh Framework Programme (FP7/2007-2013)
 * under grant agreement no. 289016.
 *
 * You may obtain a copy of the License at
 * https://github.com/GPII/universal/blob/master/LICENSE.txt
 */

"use strict";

var fluid = require("gpii-universal"),
    gpii = fluid.registerNamespace("gpii"),
    windows = fluid.registerNamespace("gpii.windows");

require("../../WindowsUtilities/WindowsUtilities.js");

fluid.registerNamespace("gpii.windows.nativeSettingsHandler");

/**
 * Gets the current double click time for mouse.
 *
 * @return {Number} The current system double click time for mouse.
 */
windows.nativeSettingsHandler.GetDoubleClickTime = function () {
    var result = windows.user32.GetDoubleClickTime();

    return fluid.toPromise(result);
};

/**
 * Sets the current double click time for mouse.
 *
 * @param {Number} num The double click time to set in the system.
 * @return {Object} Object with the error information.
 */
windows.nativeSettingsHandler.SetDoubleClickTime = function (num) {
    var pRes = fluid.promise();

    var retVal = windows.user32.SetDoubleClickTime(num);
    if (retVal !== 0) {
        pRes.resolve();
    } else {
        var lastErr = windows.kernel32.GetLastError();
        var lastErrMsg = windows.translateLastError(lastErr);

        pRes.reject({code: lastErr, msg: lastErrMsg});
    }

    return pRes;
};

/**
 * Sets the height of the double-click rectangle.
 *
 * @param {Number} num The number to be set as the height of the double-click rectangle.
 * @return {Object} Object with the error information.
 */
windows.nativeSettingsHandler.SetDoubleClickWidth = function (num) {
    var pRes = fluid.promise();

    var retVal = gpii.windows.spi.systemParametersInfo("UINT", gpii.windows.spi.actions.SPI_SETDOUBLECLKWIDTH, num, 0, 0);

    if (retVal === 0) {
        var lastErr = windows.kernel32.GetLastError();
        var lastErrMsg = windows.translateLastError(lastErr);

        pRes.reject({code: lastErr, msg: lastErrMsg});
    } else {
        pRes.resolve(retVal);
    }

    return pRes;
};

/**
 * Gets the current width of the double-click rectangle.
 *
 * @return {Number} The current value of the height for the double-click rectangle.
 */
windows.nativeSettingsHandler.GetDoubleClickWidth = function () {
    var result = windows.user32.GetSystemMetrics(windows.API_constants.SM_CXDOUBLECLK);

    return fluid.toPromise(result);
};

/**
 * Sets the width of the double-click rectangle.
 *
 * @param {Number} num The number to be set as the width of the double-click rectangle.
 * @return {Object} Object with the error information.
 */
windows.nativeSettingsHandler.SetDoubleClickHeight = function (num) {
    var pRes = fluid.promise();

    var retVal = gpii.windows.spi.systemParametersInfo("UINT", gpii.windows.spi.actions.SPI_SETDOUBLECLKHEIGHT, num, 0, 0);

    if (retVal === 0) {
        var lastErr = windows.kernel32.GetLastError();
        var lastErrMsg = windows.translateLastError(lastErr);

        pRes.reject({code: lastErr, msg: lastErrMsg});
    } else {
        pRes.resolve(retVal);
    }

    return pRes;
};

/**
 * Gets the current height of the double-click rectangle.
 *
 * @return {Number} The current value of the height for the double-click rectangle.
 */
windows.nativeSettingsHandler.GetDoubleClickHeight = function () {
    var result = windows.user32.GetSystemMetrics(windows.API_constants.SM_CYDOUBLECLK);

    return fluid.toPromise(result);
};

windows.nativeSettingsHandler.functions = {
    DoubleClickTime: {
        set: windows.nativeSettingsHandler.SetDoubleClickTime,
        get: windows.nativeSettingsHandler.GetDoubleClickTime
    },
    DoubleClickWidth: {
        set: windows.nativeSettingsHandler.SetDoubleClickWidth,
        get: windows.nativeSettingsHandler.GetDoubleClickWidth
    },
    DoubleClickHeight: {
        set: windows.nativeSettingsHandler.SetDoubleClickHeight,
        get: windows.nativeSettingsHandler.GetDoubleClickHeight
    }
};

/**
 * Helper function that converts a error to string, so the rejection from the
 * settings handler only holds a message.
 *
 * @param {Object} err The error to be stringified.
 * @return {String} The error message.
 */
windows.nativeSettingsHandler.errorInfo = function (err) {
    return "With error - '" + JSON.stringify(err) + "'";
};

/**
 * Helper function for creating a custom message for error rejection.
 *
 * @param {Promise} promise The promise to be rejected.
 * @param {String} settingKey The name of the requested setting for which an operation failed.
 * @param {Object} err The error object.
 * @param {String} message A message with information about the operation.
 */
windows.nativeSettingsHandler.reject = function (promise, settingKey, err, message) {
    var operation = message + settingKey + "' failed.";
    var errMsg = "nativeSettingsHandler" + operation + windows.nativeSettingsHandler.errorInfo(err);

    promise.reject(errMsg);
};

/**
 * Setter for the nativeSettingsHandler.
 *
 * The payload should have the following format:
 *
 * {
 *      "functionName": "FunctionName",
 *      "setParam": val
 * }
 *
 * The first two items:
 *   - function: Function name for the function to be used to set/get the value.
 *   - setParam: Parameter to be passed to the 'set' function.
 *
 * @param {Object} payload The payload.
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.setImpl = function (payload) {
    var pRes = fluid.promise();

    var fnName = fluid.get(payload, "options.functionName");
    var setFn = fluid.get(windows.nativeSettingsHandler.functions, fnName + ".set");
    var getFn = fluid.get(windows.nativeSettingsHandler.functions, fnName + ".get");
    var fnNotDef = [": Failed due to '", " " + fnName + "' function not being defined."];

    if (setFn === undefined) {
        pRes.reject("nativeSettingsHandler" + fnNotDef[0] + "set" + fnNotDef[1]);
    } else if (getFn === undefined) {
        pRes.reject("nativeSettingsHandler" + fnNotDef[0] + "get" + fnNotDef[1]);
    } else {
        var results = {};
        var settingsArray = fluid.makeArray(payload.settings);

        if (settingsArray.length === 0) {
            pRes.reject("nativeSettingsHandler: Failed due to empty payload.");
        } else {
            var uniqueSetting = settingsArray[0];
            // Get the payload value to set.
            var settingKey = fluid.keys(uniqueSetting)[0];
            var valueToSet = fluid.values(uniqueSetting)[0].value;

            // Create object for storing setting results.
            results[settingKey] = {};
            // Get the current values for the setting.
            var pGetOld = getFn();

            pGetOld.then(
                function (oldVal) {
                    // Store the current value in results.
                    fluid.set(results[settingKey], "oldValue.value", oldVal);

                    var pSet = setFn(valueToSet);

                    pSet.then(
                        function () {
                            var pGetNew = getFn();

                            pGetNew.then(
                                function (newVal) {
                                    fluid.set(results[settingKey], "newValue.value", newVal);

                                    pRes.resolve(results);
                                },
                                function (err) {
                                    windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Getting new value for setting '");
                                }
                            );
                        },
                        function (err) {
                            windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Setting new value for setting '");
                        }
                    );
                },
                function (err) {
                    windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Getting current value for setting '");
                }
            );
        }
    }

    return pRes;
};

/**
 * Getter for the nativeSettingsHandler.
 *
 * @param {Object} payload The payload.
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.getImpl = function (payload) {
    var pRes = fluid.promise();

    var fnName = fluid.get(payload, "options.functionName");
    var getFn = fluid.get(windows.nativeSettingsHandler.functions, fnName + ".get");
    var fnNotDef = [": Failed due to '", " " + fnName + "' function not being defined."];

    if (getFn === undefined) {
        pRes.reject("nativeSettingsHandler" + fnNotDef[0] + "get" + fnNotDef[1]);
    } else {
        var settingsArray = fluid.makeArray(payload.settings);

        if (settingsArray.length === 0) {
            pRes.reject("nativeSettingsHandler: Failed due to empty payload.");
        } else {
            var uniqueSetting = settingsArray[0];
            var results = {};

            // Get payload setting and prepare results for returning it
            var settingKey = fluid.keys(uniqueSetting)[0];
            results[settingKey] = {};

            var pGetRes = getFn();

            pGetRes.then(
                function (curVal) {
                    results[settingKey].value = curVal;

                    pRes.resolve(results);
                },
                function (err) {
                    windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Getting current value for setting '");
                }
            );
        }
    }

    return pRes;
};

/**
 * Invoke the settings handler.
 *
 * @param {Object} payload The payload
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.get = function (payload) {
    return gpii.settingsHandlers.invokeSettingsHandler(windows.nativeSettingsHandler.getImpl, payload);
};

/**
 * Invoke the settings handler.
 *
 * @param {Object} payload The payload
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.set = function (payload) {
    return gpii.settingsHandlers.invokeSettingsHandler(windows.nativeSettingsHandler.setImpl, payload);
};
<commit_msg>GPII-3722: Fixed several typos in functions documentation<commit_after>/*
 * Windows Native Settings Handler
 *
 * Deals with individual settings that are only accessible throught isolated
 * API calls.
 *
 * Copyright 2018 Raising the Floor - International
 *
 * Licensed under the New BSD license. You may not use this file except in
 * compliance with this License.
 *
 * The research leading to these results has received funding from the European Union's
 * Seventh Framework Programme (FP7/2007-2013)
 * under grant agreement no. 289016.
 *
 * You may obtain a copy of the License at
 * https://github.com/GPII/universal/blob/master/LICENSE.txt
 */

"use strict";

var fluid = require("gpii-universal"),
    gpii = fluid.registerNamespace("gpii"),
    windows = fluid.registerNamespace("gpii.windows");

require("../../WindowsUtilities/WindowsUtilities.js");

fluid.registerNamespace("gpii.windows.nativeSettingsHandler");

/**
 * Gets the current double click time for mouse.
 *
 * @return {Number} The current system double click time for mouse.
 */
windows.nativeSettingsHandler.GetDoubleClickTime = function () {
    var result = windows.user32.GetDoubleClickTime();

    return fluid.toPromise(result);
};

/**
 * Sets the current double click time for mouse.
 *
 * @param {Number} num The double click time to set in the system.
 * @return {Object} Object with the error information.
 */
windows.nativeSettingsHandler.SetDoubleClickTime = function (num) {
    var pRes = fluid.promise();

    var retVal = windows.user32.SetDoubleClickTime(num);
    if (retVal !== 0) {
        pRes.resolve();
    } else {
        var lastErr = windows.kernel32.GetLastError();
        var lastErrMsg = windows.translateLastError(lastErr);

        pRes.reject({code: lastErr, msg: lastErrMsg});
    }

    return pRes;
};

/**
 * Sets the width of the double-click rectangle.
 *
 * @param {Number} num The number to be set as the width of the double-click rectangle.
 * @return {Object} Object with the error information.
 */
windows.nativeSettingsHandler.SetDoubleClickWidth = function (num) {
    var pRes = fluid.promise();

    var retVal = gpii.windows.spi.systemParametersInfo("UINT", gpii.windows.spi.actions.SPI_SETDOUBLECLKWIDTH, num, 0, 0);

    if (retVal === 0) {
        var lastErr = windows.kernel32.GetLastError();
        var lastErrMsg = windows.translateLastError(lastErr);

        pRes.reject({code: lastErr, msg: lastErrMsg});
    } else {
        pRes.resolve(retVal);
    }

    return pRes;
};

/**
 * Gets the current width of the double-click rectangle.
 *
 * @return {Number} The current value of the width for the double-click rectangle.
 */
windows.nativeSettingsHandler.GetDoubleClickWidth = function () {
    var result = windows.user32.GetSystemMetrics(windows.API_constants.SM_CXDOUBLECLK);

    return fluid.toPromise(result);
};

/**
 * Sets the height of the double-click rectangle.
 *
 * @param {Number} num The number to be set as the height of the double-click rectangle.
 * @return {Object} Object with the error information.
 */
windows.nativeSettingsHandler.SetDoubleClickHeight = function (num) {
    var pRes = fluid.promise();

    var retVal = gpii.windows.spi.systemParametersInfo("UINT", gpii.windows.spi.actions.SPI_SETDOUBLECLKHEIGHT, num, 0, 0);

    if (retVal === 0) {
        var lastErr = windows.kernel32.GetLastError();
        var lastErrMsg = windows.translateLastError(lastErr);

        pRes.reject({code: lastErr, msg: lastErrMsg});
    } else {
        pRes.resolve(retVal);
    }

    return pRes;
};

/**
 * Gets the current height of the double-click rectangle.
 *
 * @return {Number} The current value of the height for the double-click rectangle.
 */
windows.nativeSettingsHandler.GetDoubleClickHeight = function () {
    var result = windows.user32.GetSystemMetrics(windows.API_constants.SM_CYDOUBLECLK);

    return fluid.toPromise(result);
};

windows.nativeSettingsHandler.functions = {
    DoubleClickTime: {
        set: windows.nativeSettingsHandler.SetDoubleClickTime,
        get: windows.nativeSettingsHandler.GetDoubleClickTime
    },
    DoubleClickWidth: {
        set: windows.nativeSettingsHandler.SetDoubleClickWidth,
        get: windows.nativeSettingsHandler.GetDoubleClickWidth
    },
    DoubleClickHeight: {
        set: windows.nativeSettingsHandler.SetDoubleClickHeight,
        get: windows.nativeSettingsHandler.GetDoubleClickHeight
    }
};

/**
 * Helper function that converts a error to string, so the rejection from the
 * settings handler only holds a message.
 *
 * @param {Object} err The error to be stringified.
 * @return {String} The error message.
 */
windows.nativeSettingsHandler.errorInfo = function (err) {
    return "With error - '" + JSON.stringify(err) + "'";
};

/**
 * Helper function for creating a custom message for error rejection.
 *
 * @param {Promise} promise The promise to be rejected.
 * @param {String} settingKey The name of the requested setting for which an operation failed.
 * @param {Object} err The error object.
 * @param {String} message A message with information about the operation.
 */
windows.nativeSettingsHandler.reject = function (promise, settingKey, err, message) {
    var operation = message + settingKey + "' failed.";
    var errMsg = "nativeSettingsHandler" + operation + windows.nativeSettingsHandler.errorInfo(err);

    promise.reject(errMsg);
};

/**
 * Setter for the nativeSettingsHandler.
 *
 * The payload should have the following format:
 *
 * {
 *      "functionName": "FunctionName",
 *      "setParam": val
 * }
 *
 * The first two items:
 *   - function: Function name for the function to be used to set/get the value.
 *   - setParam: Parameter to be passed to the 'set' function.
 *
 * @param {Object} payload The payload.
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.setImpl = function (payload) {
    var pRes = fluid.promise();

    var fnName = fluid.get(payload, "options.functionName");
    var setFn = fluid.get(windows.nativeSettingsHandler.functions, fnName + ".set");
    var getFn = fluid.get(windows.nativeSettingsHandler.functions, fnName + ".get");
    var fnNotDef = [": Failed due to '", " " + fnName + "' function not being defined."];

    if (setFn === undefined) {
        pRes.reject("nativeSettingsHandler" + fnNotDef[0] + "set" + fnNotDef[1]);
    } else if (getFn === undefined) {
        pRes.reject("nativeSettingsHandler" + fnNotDef[0] + "get" + fnNotDef[1]);
    } else {
        var results = {};
        var settingsArray = fluid.makeArray(payload.settings);

        if (settingsArray.length === 0) {
            pRes.reject("nativeSettingsHandler: Failed due to empty payload.");
        } else {
            var uniqueSetting = settingsArray[0];
            // Get the payload value to set.
            var settingKey = fluid.keys(uniqueSetting)[0];
            var valueToSet = fluid.values(uniqueSetting)[0].value;

            // Create object for storing setting results.
            results[settingKey] = {};
            // Get the current values for the setting.
            var pGetOld = getFn();

            pGetOld.then(
                function (oldVal) {
                    // Store the current value in results.
                    fluid.set(results[settingKey], "oldValue.value", oldVal);

                    var pSet = setFn(valueToSet);

                    pSet.then(
                        function () {
                            var pGetNew = getFn();

                            pGetNew.then(
                                function (newVal) {
                                    fluid.set(results[settingKey], "newValue.value", newVal);

                                    pRes.resolve(results);
                                },
                                function (err) {
                                    windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Getting new value for setting '");
                                }
                            );
                        },
                        function (err) {
                            windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Setting new value for setting '");
                        }
                    );
                },
                function (err) {
                    windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Getting current value for setting '");
                }
            );
        }
    }

    return pRes;
};

/**
 * Getter for the nativeSettingsHandler.
 *
 * @param {Object} payload The payload.
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.getImpl = function (payload) {
    var pRes = fluid.promise();

    var fnName = fluid.get(payload, "options.functionName");
    var getFn = fluid.get(windows.nativeSettingsHandler.functions, fnName + ".get");
    var fnNotDef = [": Failed due to '", " " + fnName + "' function not being defined."];

    if (getFn === undefined) {
        pRes.reject("nativeSettingsHandler" + fnNotDef[0] + "get" + fnNotDef[1]);
    } else {
        var settingsArray = fluid.makeArray(payload.settings);

        if (settingsArray.length === 0) {
            pRes.reject("nativeSettingsHandler: Failed due to empty payload.");
        } else {
            var uniqueSetting = settingsArray[0];
            var results = {};

            // Get payload setting and prepare results for returning it
            var settingKey = fluid.keys(uniqueSetting)[0];
            results[settingKey] = {};

            var pGetRes = getFn();

            pGetRes.then(
                function (curVal) {
                    results[settingKey].value = curVal;

                    pRes.resolve(results);
                },
                function (err) {
                    windows.nativeSettingsHandler.reject(pRes, settingKey, err, ": Getting current value for setting '");
                }
            );
        }
    }

    return pRes;
};

/**
 * Invoke the settings handler.
 *
 * @param {Object} payload The payload
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.get = function (payload) {
    return gpii.settingsHandlers.invokeSettingsHandler(windows.nativeSettingsHandler.getImpl, payload);
};

/**
 * Invoke the settings handler.
 *
 * @param {Object} payload The payload
 * @return {Promise} Resolves with the response.
 */
windows.nativeSettingsHandler.set = function (payload) {
    return gpii.settingsHandlers.invokeSettingsHandler(windows.nativeSettingsHandler.setImpl, payload);
};
<|endoftext|>


<commit_before>var HtmlWebpackPlugin = require("html-webpack-plugin")
var path = require("path");
var nodeModulesPath = path.resolve(__dirname, "node_modules");
var webpack = require("webpack")

module.exports = {
  // TODO: Choose between source-map and eval-source-map.
  devtool: "source-map",
  //devtool: "eval-source-map",
  devServer: {
    historyApiFallback: true
  },
  entry: "./src/index.ts",
  module: {
    loaders: [
      {
        test: /\.ejs$/,
        loader: "ejs-loader"
      },
      {
        test: /\.ts$/,
        loader: "ts-loader"
      }
    ],
    preLoaders: [
      // All output .js files will have any sourcemaps re-processed by source-map-loader.
      {
        test: /\.js$/,
        loader: "source-map-loader"
      }
    ]
  },
  output: {
    path: "dist",
    filename: "bundle.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.ejs"
    }),
    new webpack.ProvidePlugin({
        _: "underscore"
    })
  ],
  resolve: {
    // Add .ts as resolvable extensions.
    extensions: ["", ".js", ".ts"]
  }
}
<commit_msg>source-map look good<commit_after>var HtmlWebpackPlugin = require("html-webpack-plugin")
var path = require("path");
var nodeModulesPath = path.resolve(__dirname, "node_modules");
var webpack = require("webpack")

module.exports = {
  devtool: "source-map",
  devServer: {
    historyApiFallback: true
  },
  entry: "./src/index.ts",
  module: {
    loaders: [
      {
        test: /\.ejs$/,
        loader: "ejs-loader"
      },
      {
        test: /\.ts$/,
        loader: "ts-loader"
      }
    ],
    preLoaders: [
      // All output .js files will have any sourcemaps re-processed by source-map-loader.
      {
        test: /\.js$/,
        loader: "source-map-loader"
      }
    ]
  },
  output: {
    path: "dist",
    filename: "bundle.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.ejs"
    }),
    new webpack.ProvidePlugin({
        _: "underscore"
    })
  ],
  resolve: {
    // Add .ts as resolvable extensions.
    extensions: ["", ".js", ".ts"]
  }
}
<|endoftext|>


<commit_before>// Copyright 2015, University of Colorado Boulder

/**
 * Lightweight event & listener abstraction for a single event type.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var inherit = require( 'PHET_CORE/inherit' );
  var phetioEvents = require( 'ifphetio!PHET_IO/phetioEvents' );
  var Tandem = require( 'TANDEM/Tandem' );
  var TEmitter = require( 'AXON/TEmitter' );

  /**
   *
   * @constructor
   */
  function Emitter( options ) {

    // @private {Function[]} - the listeners to emit to
    this.listeners = [];

    // @private - during emit() keep track of which listeners should receive events in order to manage removal of
    //          - listeners during emit()
    this.listenersToEmitTo = [];

    options = _.extend( {
      phetioArgumentTypes: [], // {Object[]} - for serializing/displaying the values during emit. Key = arg name, value = TType
      tandem: Tandem.tandemOptional()
      // see also phetio options in phetio.addInstance
    }, options );

    var self = this;

    // @private
    this.tandem = options.tandem;

    // @private
    this.phetioArgumentTypes = options.phetioArgumentTypes;

    // Tandem registration
    this.ttype = TEmitter( options.phetioArgumentTypes );
    options.tandem.addInstance( this, this.ttype, options );

    // @private
    this.disposeEmitter = function() {

      // See https://github.com/phetsims/axon/issues/124
      self.listeners.length = 0;

      // Tandem de-registration
      options.tandem.removeInstance( self );
    };
  }

  axon.register( 'Emitter', Emitter );

  return inherit( Object, Emitter, {

    /**
     * Dispose an Emitter that is no longer used.  Like Property.dispose, this method checks that there are no leaked
     * listeners.
     */
    dispose: function() {
      this.disposeEmitter();
    },

    /**
     * Adds a listener
     * @param {function} listener
     * @public
     */
    addListener: function( listener ) {

      assert && assert( this.listeners.indexOf( listener ) === -1, 'Cannot add the same listener twice' );

      // If callbacks are in progress, make a copy of the current list of listeners--the newly added listener
      // will be available for the next emit() but not the one in progress.  This is to match behavior with removeListener
      this.defendCallbacks();

      this.listeners.push( listener );
    },

    /**
     * Removes a listener
     * @param {function} listener
     * @public
     */
    removeListener: function( listener ) {

      var index = this.listeners.indexOf( listener );
      assert && assert( index >= 0, 'tried to removeListener on something that wasn\'t a listener' );

      // If callbacks are in progress, make a copy of the current list of listeners--the removed listener
      // will remain in the list and receive a callback for this emit call, see #72
      this.defendCallbacks();

      this.listeners.splice( index, 1 );
    },

    /**
     * Removes all the listeners
     * @public
     */
    removeAllListeners: function() {
      while ( this.listeners.length > 0 ) {
        this.removeListener( this.listeners[ 0 ] );
      }
    },

    /**
     * If processing callbacks during an emit() call and addListener/removeListener() is called,
     * make a defensive copy of the array of listener before changing the array, and use it for
     * the rest of the callbacks until the emit call has completed.
     * @private
     */
    defendCallbacks: function() {

      for ( var i = this.listenersToEmitTo.length - 1; i >= 0; i-- ) {

        // Once we meet a level that was already defended, we can stop, since all previous levels are also defended
        if ( this.listenersToEmitTo[ i ].defended ) {
          break;
        }
        else {
          var defendedListeners = this.listeners.slice();

          // Mark copies as 'defended' so that it will use the original listeners when emit started and not the modified list.
          defendedListeners.defended = true;
          this.listenersToEmitTo[ i ] = defendedListeners;
        }
      }
    },

    /**
     * Emits a single event.
     * This method is called many times in a simulation and must be well-optimized.
     * @public
     */
    emit: function() {

      var id = this.tandem.isLegalAndUsable() && phetioEvents.start( 'model', this.tandem.id, this.ttype, 'emitted' );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]();
      }

      this.listenersToEmitTo.pop();
      this.tandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with one argument.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @public
     */
    emit1: function( arg0 ) {

      // TODO: name the args for the data stream

      var id = this.tandem.isLegalAndUsable() && phetioEvents.start( 'model', this.tandem.id, this.ttype, 'emitted', {
        args: [ this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ) ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0 );
      }

      this.listenersToEmitTo.pop();
      this.tandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with two arguments.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @param {*} arg1
     * @public
     */
    emit2: function( arg0, arg1 ) {
      var id = this.tandem.isLegalAndUsable() && phetioEvents.start( 'model', this.tandem.id, this.ttype, 'emitted', {
        args: [
          this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ),
          this.phetioArgumentTypes[ 1 ].toStateObject( arg1 )
        ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0, arg1 );
      }

      this.listenersToEmitTo.pop();
      this.tandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with three arguments.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @param {*} arg1
     * @param {*} arg2
     * @public
     */
    emit3: function( arg0, arg1, arg2 ) {
      var id = this.tandem.isLegalAndUsable() && phetioEvents.start( 'model', this.tandem.id, this.ttype, 'emitted', {
        args: [
          this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ),
          this.phetioArgumentTypes[ 1 ].toStateObject( arg1 ),
          this.phetioArgumentTypes[ 2 ].toStateObject( arg2 )
        ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0, arg1, arg2 );
      }

      this.listenersToEmitTo.pop();
      this.tandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with three arguments.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @param {*} arg1
     * @param {*} arg2
     * @param {*} arg3
     * @public
     */
    emit4: function( arg0, arg1, arg2, arg3 ) {
      var id = this.tandem.isLegalAndUsable() && phetioEvents.start( 'model', this.tandem.id, this.ttype, 'emitted', {
        args: [
          this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ),
          this.phetioArgumentTypes[ 1 ].toStateObject( arg1 ),
          this.phetioArgumentTypes[ 2 ].toStateObject( arg2 ),
          this.phetioArgumentTypes[ 3 ].toStateObject( arg3 )
        ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0, arg1, arg2, arg3 );
      }

      this.listenersToEmitTo.pop();
      this.tandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Checks whether a listener is registered with this Emitter
     * @param {function} listener
     * @returns {boolean}
     * @public
     */
    hasListener: function( listener ) {
      assert && assert( arguments.length === 1, 'Emitter.hasListener should be called with 1 argument' );
      return this.listeners.indexOf( listener ) >= 0;
    },

    /**
     * Returns true if there are any listeners.
     * @returns {boolean}
     * @public
     */
    hasListeners: function() {
      assert && assert( arguments.length === 0, 'Emitter.hasListeners should be called without arguments' );
      return this.listeners.length > 0;
    }
  } );
} );<commit_msg>Renamed this.tandem => this.emitterTandem, see https://github.com/phetsims/phet-io/issues/1239<commit_after>// Copyright 2015, University of Colorado Boulder

/**
 * Lightweight event & listener abstraction for a single event type.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var inherit = require( 'PHET_CORE/inherit' );
  var phetioEvents = require( 'ifphetio!PHET_IO/phetioEvents' );
  var Tandem = require( 'TANDEM/Tandem' );
  var TEmitter = require( 'AXON/TEmitter' );

  /**
   *
   * @constructor
   */
  function Emitter( options ) {

    // @private {Function[]} - the listeners to emit to
    this.listeners = [];

    // @private - during emit() keep track of which listeners should receive events in order to manage removal of
    //          - listeners during emit()
    this.listenersToEmitTo = [];

    options = _.extend( {
      phetioArgumentTypes: [], // {Object[]} - for serializing/displaying the values during emit. Key = arg name, value = TType
      tandem: Tandem.tandemOptional()
      // see also phetio options in phetio.addInstance
    }, options );

    var self = this;

    // @private
    this.emitterTandem = options.tandem;

    // @private
    this.phetioArgumentTypes = options.phetioArgumentTypes;

    // Tandem registration
    this.ttype = TEmitter( options.phetioArgumentTypes );
    options.tandem.addInstance( this, this.ttype, options );

    // @private
    this.disposeEmitter = function() {

      // See https://github.com/phetsims/axon/issues/124
      self.listeners.length = 0;

      // Tandem de-registration
      options.tandem.removeInstance( self );
    };
  }

  axon.register( 'Emitter', Emitter );

  return inherit( Object, Emitter, {

    /**
     * Dispose an Emitter that is no longer used.  Like Property.dispose, this method checks that there are no leaked
     * listeners.
     */
    dispose: function() {
      this.disposeEmitter();
    },

    /**
     * Adds a listener
     * @param {function} listener
     * @public
     */
    addListener: function( listener ) {

      assert && assert( this.listeners.indexOf( listener ) === -1, 'Cannot add the same listener twice' );

      // If callbacks are in progress, make a copy of the current list of listeners--the newly added listener
      // will be available for the next emit() but not the one in progress.  This is to match behavior with removeListener
      this.defendCallbacks();

      this.listeners.push( listener );
    },

    /**
     * Removes a listener
     * @param {function} listener
     * @public
     */
    removeListener: function( listener ) {

      var index = this.listeners.indexOf( listener );
      assert && assert( index >= 0, 'tried to removeListener on something that wasn\'t a listener' );

      // If callbacks are in progress, make a copy of the current list of listeners--the removed listener
      // will remain in the list and receive a callback for this emit call, see #72
      this.defendCallbacks();

      this.listeners.splice( index, 1 );
    },

    /**
     * Removes all the listeners
     * @public
     */
    removeAllListeners: function() {
      while ( this.listeners.length > 0 ) {
        this.removeListener( this.listeners[ 0 ] );
      }
    },

    /**
     * If processing callbacks during an emit() call and addListener/removeListener() is called,
     * make a defensive copy of the array of listener before changing the array, and use it for
     * the rest of the callbacks until the emit call has completed.
     * @private
     */
    defendCallbacks: function() {

      for ( var i = this.listenersToEmitTo.length - 1; i >= 0; i-- ) {

        // Once we meet a level that was already defended, we can stop, since all previous levels are also defended
        if ( this.listenersToEmitTo[ i ].defended ) {
          break;
        }
        else {
          var defendedListeners = this.listeners.slice();

          // Mark copies as 'defended' so that it will use the original listeners when emit started and not the modified list.
          defendedListeners.defended = true;
          this.listenersToEmitTo[ i ] = defendedListeners;
        }
      }
    },

    /**
     * Emits a single event.
     * This method is called many times in a simulation and must be well-optimized.
     * @public
     */
    emit: function() {

      var id = this.emitterTandem.isLegalAndUsable() && phetioEvents.start( 'model', this.emitterTandem.id, this.ttype, 'emitted' );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]();
      }

      this.listenersToEmitTo.pop();
      this.emitterTandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with one argument.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @public
     */
    emit1: function( arg0 ) {

      // TODO: name the args for the data stream

      var id = this.emitterTandem.isLegalAndUsable() && phetioEvents.start( 'model', this.emitterTandem.id, this.ttype, 'emitted', {
        args: [ this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ) ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0 );
      }

      this.listenersToEmitTo.pop();
      this.emitterTandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with two arguments.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @param {*} arg1
     * @public
     */
    emit2: function( arg0, arg1 ) {
      var id = this.emitterTandem.isLegalAndUsable() && phetioEvents.start( 'model', this.emitterTandem.id, this.ttype, 'emitted', {
        args: [
          this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ),
          this.phetioArgumentTypes[ 1 ].toStateObject( arg1 )
        ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0, arg1 );
      }

      this.listenersToEmitTo.pop();
      this.emitterTandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with three arguments.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @param {*} arg1
     * @param {*} arg2
     * @public
     */
    emit3: function( arg0, arg1, arg2 ) {
      var id = this.emitterTandem.isLegalAndUsable() && phetioEvents.start( 'model', this.emitterTandem.id, this.ttype, 'emitted', {
        args: [
          this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ),
          this.phetioArgumentTypes[ 1 ].toStateObject( arg1 ),
          this.phetioArgumentTypes[ 2 ].toStateObject( arg2 )
        ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0, arg1, arg2 );
      }

      this.listenersToEmitTo.pop();
      this.emitterTandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Emits a single event with three arguments.  This is a copy-paste of emit() for performance reasons.
     * @param {*} arg0
     * @param {*} arg1
     * @param {*} arg2
     * @param {*} arg3
     * @public
     */
    emit4: function( arg0, arg1, arg2, arg3 ) {
      var id = this.emitterTandem.isLegalAndUsable() && phetioEvents.start( 'model', this.emitterTandem.id, this.ttype, 'emitted', {
        args: [
          this.phetioArgumentTypes[ 0 ].toStateObject( arg0 ),
          this.phetioArgumentTypes[ 1 ].toStateObject( arg1 ),
          this.phetioArgumentTypes[ 2 ].toStateObject( arg2 ),
          this.phetioArgumentTypes[ 3 ].toStateObject( arg3 )
        ]
      } );
      this.listenersToEmitTo.push( this.listeners );
      var lastEntry = this.listenersToEmitTo.length - 1;

      for ( var i = 0; i < this.listenersToEmitTo[ lastEntry ].length; i++ ) {
        this.listenersToEmitTo[ lastEntry ][ i ]( arg0, arg1, arg2, arg3 );
      }

      this.listenersToEmitTo.pop();
      this.emitterTandem.isLegalAndUsable() && phetioEvents.end( id );
    },

    /**
     * Checks whether a listener is registered with this Emitter
     * @param {function} listener
     * @returns {boolean}
     * @public
     */
    hasListener: function( listener ) {
      assert && assert( arguments.length === 1, 'Emitter.hasListener should be called with 1 argument' );
      return this.listeners.indexOf( listener ) >= 0;
    },

    /**
     * Returns true if there are any listeners.
     * @returns {boolean}
     * @public
     */
    hasListeners: function() {
      assert && assert( arguments.length === 0, 'Emitter.hasListeners should be called without arguments' );
      return this.listeners.length > 0;
    }
  } );
} );<|endoftext|>


<commit_before>//WARNING: no log() function usage before init.js

exports.core.device = 0
exports.core.vendor = ""

exports.core.trace = { key: false, focus: false }

exports.core.keyCodes = {
	13: 'Select',
	27: 'Back',
	37: 'Left',
	32: 'Space',
	33: 'PageUp',
	34: 'PageDown',
	38: 'Up',
	39: 'Right',
	40: 'Down',
	48: '0',
	49: '1',
	50: '2',
	51: '3',
	52: '4',
	53: '5',
	54: '6',
	55: '7',
	56: '8',
	57: '9',
	112: 'Red',
	113: 'Green',
	114: 'Yellow',
	115: 'Blue'
}

var copyArguments = function(args, src, prefix) {
	var copy = Array.prototype.slice.call(args, src)
	if (prefix !== undefined)
		copy.unshift(prefix)
	return copy
}

exports.core.copyArguments = copyArguments

/* ${init.js} */

if (log === null)
	log = console.log.bind(console)

/** @const */
/** @param {string} text @param {...} args */
_globals.qsTr = function(text, args) { return _globals._context.qsTr.apply(qml._context, arguments) }

var colorTable = {
	'maroon':	'800000',
	'red':		'ff0000',
	'orange':	'ffA500',
	'yellow':	'ffff00',
	'olive':	'808000',
	'purple':	'800080',
	'fuchsia':	'ff00ff',
	'white':	'ffffff',
	'lime':		'00ff00',
	'green':	'008000',
	'navy':		'000080',
	'blue':		'0000ff',
	'aqua':		'00ffff',
	'teal':		'008080',
	'black':	'000000',
	'silver':	'c0c0c0',
	'gray':		'080808',
	'transparent': '0000'
}

var safeCallImpl = function(callback, args, onError) {
	try { return callback.apply(null, args) } catch(ex) { onError(ex) }
}

exports.core.safeCall = function(args, onError) {
	return function(callback) { return safeCallImpl(callback, args, onError) }
}

/**
 * @constructor
 */
exports.core.CoreObject = function() { }
exports.core.CoreObject.prototype.constructor = exports.core.CoreObject
exports.core.CoreObject.prototype.__create = function() { }
exports.core.CoreObject.prototype.__setup = function() { }

/** @constructor */
exports.core.Color = function(value) {
	if (Array.isArray(value)) {
		this.r = value[0]
		this.g = value[1]
		this.b = value[2]
		this.a = value[3] !== undefined? value[3]: 255
		return
	}
	if (typeof value !== 'string')
	{
		this.r = this.b = this.a = 255
		this.g = 0
		log("invalid color specification: " + value)
		return
	}
	var triplet
	if (value.substring(0, 4) == "rgba") {
		var b = value.indexOf('('), e = value.lastIndexOf(')')
		value = value.substring(b + 1, e).split(',')
		this.r = parseInt(value[0], 10)
		this.g = parseInt(value[1], 10)
		this.b = parseInt(value[2], 10)
		this.a = Math.floor(parseFloat(value[3]) * 255)
		return
	}
	else {
		var h = value.charAt(0);
		if (h != '#')
			triplet = colorTable[value];
		else
			triplet = value.substring(1)
	}
	if (!triplet) {
		this.r = 255
		this.g = 0
		this.b = 255
		log("invalid color specification: " + value)
		return
	}

	var len = triplet.length;
	if (len == 3 || len == 4) {
		var r = parseInt(triplet.charAt(0), 16)
		var g = parseInt(triplet.charAt(1), 16)
		var b = parseInt(triplet.charAt(2), 16)
		var a = (len == 4)? parseInt(triplet.charAt(3), 16): 15
		this.r = (r << 4) | r;
		this.g = (g << 4) | g;
		this.b = (b << 4) | b;
		this.a = (a << 4) | a;
	} else if (len == 6 || len == 8) {
		this.r = parseInt(triplet.substring(0, 2), 16)
		this.g = parseInt(triplet.substring(2, 4), 16)
		this.b = parseInt(triplet.substring(4, 6), 16)
		this.a = (len == 8)? parseInt(triplet.substring(6, 8), 16): 255
	} else
		throw new Error("invalid color specification: " + value)
}
exports.core.Color.prototype.constructor = exports.core.Color
/** @const */
var Color = exports.core.Color

exports.core.Color.prototype.rgba = function() {
	return "rgba(" + this.r + "," + this.g + "," + this.b + "," + (this.a / 255) + ")";
}

exports.core.normalizeColor = function(spec) {
	return (new Color(spec)).rgba()
}

exports.core.mixColor = function(specA, specB, r) {
	var a = new Color(specA)
	var b = new Color(specB)
	var mix = function(a, b, r) { return Math.floor((b - a) * r + a) }
	return [mix(a.r, b.r, r), mix(a.g, b.g, r), mix(a.b, b.b, r), mix(a.a, b.a, r)]
}

/** @constructor */
exports.core.DelayedAction = function(context, action) {
	this.context = context
	this.action = function() {
		this._scheduled = false
		action()
	}.bind(this)
}

exports.core.DelayedAction.prototype.schedule = function() {
	if (!this._scheduled) {
		this._scheduled = true
		this.context.scheduleAction(this.action)
	}
}

exports.addProperty = function(proto, type, name, defaultValue) {
	var convert
	switch(type) {
		case 'enum':
		case 'int':		convert = function(value) { return parseInt(value, 0) }; break
		case 'bool':	convert = function(value) { return value? true: false }; break
		case 'real':	convert = function(value) { return parseFloat(value) }; break
		case 'string':	convert = function(value) { return String(value) }; break
		default:		convert = function(value) { return value }; break
	}

	if (defaultValue !== undefined) {
		defaultValue = convert(defaultValue)
	} else {
		switch(type) {
			case 'enum': //fixme: add default value here
			case 'int':		defaultValue = 0; break
			case 'bool':	defaultValue = false; break
			case 'real':	defaultValue = 0.0; break
			case 'string':	defaultValue = ""; break
			case 'array':	defaultValue = []; break
			case 'Color':	defaultValue = '#0000'; break
			default:
				defaultValue = (type[0].toUpperCase() == type[0])? null: undefined
		}
	}

	var storageName = '__property_' + name
	var forwardName = '__forward_' + name

	Object.defineProperty(proto, name, {
		get: function() {
			var p = this[storageName]
			return p !== undefined?
				p.interpolatedValue !== undefined? p.interpolatedValue: p.value:
				defaultValue
		},

		set: function(newValue) {
			newValue = convert(newValue)
			var p = this[storageName]
			if (p === undefined) { //no storage
				if (newValue === defaultValue) //value == defaultValue, no storage allocation
					return

				p = this[storageName] = { value : defaultValue }
			}
			var backend = this._context.backend
			var animation = this.getAnimation(name)
			if (animation && p.value !== newValue) {
				if (p.frameRequest)
					backend.cancelAnimationFrame(p.frameRequest)

				var now = new Date()
				p.started = now.getTime() + now.getMilliseconds() / 1000.0

				var src = p.interpolatedValue !== undefined? p.interpolatedValue: p.value
				var dst = newValue

				var self = this

				var complete = function() {
					backend.cancelAnimationFrame(p.frameRequest)
					p.frameRequest = undefined
					animation.complete = function() { }
					animation.running = false
					p.interpolatedValue = undefined
					p.started = undefined
					self._update(name, dst, src)
				}

				var duration = animation.duration

				var nextFrame = function() {
					var date = new Date()
					var now = date.getTime() + date.getMilliseconds() / 1000.0
					var t = 1.0 * (now - p.started) / duration
					if (t >= 1) {
						complete()
					} else {
						p.interpolatedValue = convert(animation.interpolate(dst, src, t))
						self._update(name, p.interpolatedValue, src)
						p.frameRequest = backend.requestAnimationFrame(nextFrame)
					}
				}

				p.frameRequest = backend.requestAnimationFrame(nextFrame)

				animation.running = true
				animation.complete = complete
			}
			var oldValue = p.value
			if (oldValue !== newValue) {
				var forwardTarget = this[forwardName]
				if (forwardTarget !== undefined) {
					if (oldValue !== null && (oldValue instanceof Object)) {
						//forward property update for mixins
						var forwardedOldValue = oldValue[forwardTarget]
						if (newValue !== forwardedOldValue) {
							oldValue[forwardTarget] = newValue
							this._update(name, newValue, forwardedOldValue)
						}
						return
					} else if (newValue instanceof Object) {
						//first assignment of mixin
						this.connectOnChanged(newValue, forwardTarget, function(v, ov) { this._update(name, v, ov) }.bind(this))
					}
				}
				p.value = newValue
				if ((!animation || !animation.running) && newValue == defaultValue)
					delete this[storageName]
				if (!animation)
					this._update(name, newValue, oldValue)
			}
		},
		enumerable: true
	})
}

exports.addAliasProperty = function(self, name, getObject, srcProperty) {
	var target = getObject()
	self.connectOnChanged(target, srcProperty, function(value) { self._update(name, value) })

	Object.defineProperty(self, name, {
		get: function() { return target[srcProperty] },
		set: function(value) { target[srcProperty] = value },
		enumerable: true
	})
}

exports.core.createSignal = function(name) {
	return function() { this.emit.apply(this, copyArguments(arguments, 0, name)) }
}
exports.core.createSignalForwarder = function(object, name) {
	return (function() { object.emit.apply(object, copyArguments(arguments, 0, name)) })
}

/** @constructor */
exports.core.EventBinder = function(target) {
	this.target = target
	this.callbacks = {}
	this.enabled = false
}

exports.core.EventBinder.prototype.on = function(event, callback) {
	if (event in this.callbacks)
		throw new Error('double adding of event (' + event + ')')
	this.callbacks[event] = callback
	if (this.enabled)
		this.target.on(event, callback)
}

exports.core.EventBinder.prototype.constructor = exports.core.EventBinder

exports.core.EventBinder.prototype.enable = function(value) {
	if (value != this.enabled) {
		var target = this.target
		this.enabled = value
		if (value) {
			for(var event in this.callbacks)
				target.on(event, this.callbacks[event])
		} else {
			for(var event in this.callbacks)
				target.removeListener(event, this.callbacks[event])
		}
	}
}

var protoEvent = function(prefix, proto, name, callback) {
	var name = '__' + prefix + '__' + name
	if (name in proto) {
		proto[name] = function() {
			try {
				callback.apply(this, arguments)
			} catch(ex) {
				log('error invoking prototype event ' + prefix + ':' + name, ex, ex.stack)
			}
		}
	} else
		proto[name] = [callback]
}

exports.core._protoOn = function(proto, name, callback)
{ protoEvent('on', proto, name, callback) }

exports.core._protoChanged = function(proto, name, callback)
{ protoEvent('changed', proto, name, callback) }
<commit_msg>renamed protoChanged to protoOnChanged, removed array, use nested functions<commit_after>//WARNING: no log() function usage before init.js

exports.core.device = 0
exports.core.vendor = ""

exports.core.trace = { key: false, focus: false }

exports.core.keyCodes = {
	13: 'Select',
	27: 'Back',
	37: 'Left',
	32: 'Space',
	33: 'PageUp',
	34: 'PageDown',
	38: 'Up',
	39: 'Right',
	40: 'Down',
	48: '0',
	49: '1',
	50: '2',
	51: '3',
	52: '4',
	53: '5',
	54: '6',
	55: '7',
	56: '8',
	57: '9',
	112: 'Red',
	113: 'Green',
	114: 'Yellow',
	115: 'Blue'
}

var copyArguments = function(args, src, prefix) {
	var copy = Array.prototype.slice.call(args, src)
	if (prefix !== undefined)
		copy.unshift(prefix)
	return copy
}

exports.core.copyArguments = copyArguments

/* ${init.js} */

if (log === null)
	log = console.log.bind(console)

/** @const */
/** @param {string} text @param {...} args */
_globals.qsTr = function(text, args) { return _globals._context.qsTr.apply(qml._context, arguments) }

var colorTable = {
	'maroon':	'800000',
	'red':		'ff0000',
	'orange':	'ffA500',
	'yellow':	'ffff00',
	'olive':	'808000',
	'purple':	'800080',
	'fuchsia':	'ff00ff',
	'white':	'ffffff',
	'lime':		'00ff00',
	'green':	'008000',
	'navy':		'000080',
	'blue':		'0000ff',
	'aqua':		'00ffff',
	'teal':		'008080',
	'black':	'000000',
	'silver':	'c0c0c0',
	'gray':		'080808',
	'transparent': '0000'
}

var safeCallImpl = function(callback, args, onError) {
	try { return callback.apply(null, args) } catch(ex) { onError(ex) }
}

exports.core.safeCall = function(args, onError) {
	return function(callback) { return safeCallImpl(callback, args, onError) }
}

/**
 * @constructor
 */
exports.core.CoreObject = function() { }
exports.core.CoreObject.prototype.constructor = exports.core.CoreObject
exports.core.CoreObject.prototype.__create = function() { }
exports.core.CoreObject.prototype.__setup = function() { }

/** @constructor */
exports.core.Color = function(value) {
	if (Array.isArray(value)) {
		this.r = value[0]
		this.g = value[1]
		this.b = value[2]
		this.a = value[3] !== undefined? value[3]: 255
		return
	}
	if (typeof value !== 'string')
	{
		this.r = this.b = this.a = 255
		this.g = 0
		log("invalid color specification: " + value)
		return
	}
	var triplet
	if (value.substring(0, 4) == "rgba") {
		var b = value.indexOf('('), e = value.lastIndexOf(')')
		value = value.substring(b + 1, e).split(',')
		this.r = parseInt(value[0], 10)
		this.g = parseInt(value[1], 10)
		this.b = parseInt(value[2], 10)
		this.a = Math.floor(parseFloat(value[3]) * 255)
		return
	}
	else {
		var h = value.charAt(0);
		if (h != '#')
			triplet = colorTable[value];
		else
			triplet = value.substring(1)
	}
	if (!triplet) {
		this.r = 255
		this.g = 0
		this.b = 255
		log("invalid color specification: " + value)
		return
	}

	var len = triplet.length;
	if (len == 3 || len == 4) {
		var r = parseInt(triplet.charAt(0), 16)
		var g = parseInt(triplet.charAt(1), 16)
		var b = parseInt(triplet.charAt(2), 16)
		var a = (len == 4)? parseInt(triplet.charAt(3), 16): 15
		this.r = (r << 4) | r;
		this.g = (g << 4) | g;
		this.b = (b << 4) | b;
		this.a = (a << 4) | a;
	} else if (len == 6 || len == 8) {
		this.r = parseInt(triplet.substring(0, 2), 16)
		this.g = parseInt(triplet.substring(2, 4), 16)
		this.b = parseInt(triplet.substring(4, 6), 16)
		this.a = (len == 8)? parseInt(triplet.substring(6, 8), 16): 255
	} else
		throw new Error("invalid color specification: " + value)
}
exports.core.Color.prototype.constructor = exports.core.Color
/** @const */
var Color = exports.core.Color

exports.core.Color.prototype.rgba = function() {
	return "rgba(" + this.r + "," + this.g + "," + this.b + "," + (this.a / 255) + ")";
}

exports.core.normalizeColor = function(spec) {
	return (new Color(spec)).rgba()
}

exports.core.mixColor = function(specA, specB, r) {
	var a = new Color(specA)
	var b = new Color(specB)
	var mix = function(a, b, r) { return Math.floor((b - a) * r + a) }
	return [mix(a.r, b.r, r), mix(a.g, b.g, r), mix(a.b, b.b, r), mix(a.a, b.a, r)]
}

/** @constructor */
exports.core.DelayedAction = function(context, action) {
	this.context = context
	this.action = function() {
		this._scheduled = false
		action()
	}.bind(this)
}

exports.core.DelayedAction.prototype.schedule = function() {
	if (!this._scheduled) {
		this._scheduled = true
		this.context.scheduleAction(this.action)
	}
}

exports.addProperty = function(proto, type, name, defaultValue) {
	var convert
	switch(type) {
		case 'enum':
		case 'int':		convert = function(value) { return parseInt(value, 0) }; break
		case 'bool':	convert = function(value) { return value? true: false }; break
		case 'real':	convert = function(value) { return parseFloat(value) }; break
		case 'string':	convert = function(value) { return String(value) }; break
		default:		convert = function(value) { return value }; break
	}

	if (defaultValue !== undefined) {
		defaultValue = convert(defaultValue)
	} else {
		switch(type) {
			case 'enum': //fixme: add default value here
			case 'int':		defaultValue = 0; break
			case 'bool':	defaultValue = false; break
			case 'real':	defaultValue = 0.0; break
			case 'string':	defaultValue = ""; break
			case 'array':	defaultValue = []; break
			case 'Color':	defaultValue = '#0000'; break
			default:
				defaultValue = (type[0].toUpperCase() == type[0])? null: undefined
		}
	}

	var storageName = '__property_' + name
	var forwardName = '__forward_' + name

	Object.defineProperty(proto, name, {
		get: function() {
			var p = this[storageName]
			return p !== undefined?
				p.interpolatedValue !== undefined? p.interpolatedValue: p.value:
				defaultValue
		},

		set: function(newValue) {
			newValue = convert(newValue)
			var p = this[storageName]
			if (p === undefined) { //no storage
				if (newValue === defaultValue) //value == defaultValue, no storage allocation
					return

				p = this[storageName] = { value : defaultValue }
			}
			var backend = this._context.backend
			var animation = this.getAnimation(name)
			if (animation && p.value !== newValue) {
				if (p.frameRequest)
					backend.cancelAnimationFrame(p.frameRequest)

				var now = new Date()
				p.started = now.getTime() + now.getMilliseconds() / 1000.0

				var src = p.interpolatedValue !== undefined? p.interpolatedValue: p.value
				var dst = newValue

				var self = this

				var complete = function() {
					backend.cancelAnimationFrame(p.frameRequest)
					p.frameRequest = undefined
					animation.complete = function() { }
					animation.running = false
					p.interpolatedValue = undefined
					p.started = undefined
					self._update(name, dst, src)
				}

				var duration = animation.duration

				var nextFrame = function() {
					var date = new Date()
					var now = date.getTime() + date.getMilliseconds() / 1000.0
					var t = 1.0 * (now - p.started) / duration
					if (t >= 1) {
						complete()
					} else {
						p.interpolatedValue = convert(animation.interpolate(dst, src, t))
						self._update(name, p.interpolatedValue, src)
						p.frameRequest = backend.requestAnimationFrame(nextFrame)
					}
				}

				p.frameRequest = backend.requestAnimationFrame(nextFrame)

				animation.running = true
				animation.complete = complete
			}
			var oldValue = p.value
			if (oldValue !== newValue) {
				var forwardTarget = this[forwardName]
				if (forwardTarget !== undefined) {
					if (oldValue !== null && (oldValue instanceof Object)) {
						//forward property update for mixins
						var forwardedOldValue = oldValue[forwardTarget]
						if (newValue !== forwardedOldValue) {
							oldValue[forwardTarget] = newValue
							this._update(name, newValue, forwardedOldValue)
						}
						return
					} else if (newValue instanceof Object) {
						//first assignment of mixin
						this.connectOnChanged(newValue, forwardTarget, function(v, ov) { this._update(name, v, ov) }.bind(this))
					}
				}
				p.value = newValue
				if ((!animation || !animation.running) && newValue == defaultValue)
					delete this[storageName]
				if (!animation)
					this._update(name, newValue, oldValue)
			}
		},
		enumerable: true
	})
}

exports.addAliasProperty = function(self, name, getObject, srcProperty) {
	var target = getObject()
	self.connectOnChanged(target, srcProperty, function(value) { self._update(name, value) })

	Object.defineProperty(self, name, {
		get: function() { return target[srcProperty] },
		set: function(value) { target[srcProperty] = value },
		enumerable: true
	})
}

exports.core.createSignal = function(name) {
	return function() { this.emit.apply(this, copyArguments(arguments, 0, name)) }
}
exports.core.createSignalForwarder = function(object, name) {
	return (function() { object.emit.apply(object, copyArguments(arguments, 0, name)) })
}

/** @constructor */
exports.core.EventBinder = function(target) {
	this.target = target
	this.callbacks = {}
	this.enabled = false
}

exports.core.EventBinder.prototype.on = function(event, callback) {
	if (event in this.callbacks)
		throw new Error('double adding of event (' + event + ')')
	this.callbacks[event] = callback
	if (this.enabled)
		this.target.on(event, callback)
}

exports.core.EventBinder.prototype.constructor = exports.core.EventBinder

exports.core.EventBinder.prototype.enable = function(value) {
	if (value != this.enabled) {
		var target = this.target
		this.enabled = value
		if (value) {
			for(var event in this.callbacks)
				target.on(event, this.callbacks[event])
		} else {
			for(var event in this.callbacks)
				target.removeListener(event, this.callbacks[event])
		}
	}
}

var protoEvent = function(prefix, proto, name, callback) {
	var name = '__' + prefix + '__' + name
	if (name in proto) {
		proto[name] = function() {
			try {
				callback.apply(this, arguments)
			} catch(ex) {
				log('error invoking base prototype event ' + prefix + ':' + name, ex, ex.stack)
			}
		}
	} else
		proto[name] = callback
}

exports.core._protoOn = function(proto, name, callback)
{ protoEvent('on', proto, name, callback) }

exports.core._protoOnChanged = function(proto, name, callback)
{ protoEvent('changed', proto, name, callback) }
<|endoftext|>