<commit_before>import { Communicator, ReactivityProvider } from '/client/imports/facades';
import { Notification, ErrorHandler, SessionManager } from '/client/imports/modules';
import Helper from '/client/imports/helpers/helper';

const UserManagementTree = function () {
  this.loading = false;
  this.defaultInformationText = '';
};

const populatePrivileges = function (result, role, key, index) {
  for (let i = 0; i < role[key].length; i += 1) {
    result[index].children.push({
      data: [
        {
          privilege: true,
          privilegeType: this.getPrivilegeType(role[key][i].resource),
        }
      ],
      text: this.getPrivilegeText(role[key][i].resource),
      icon: 'fa fa-gears',
      children: this.getPrivilegeActions(role[key][i].actions),
    });
  }
};

const populateRoles = function (result, user, key, index) {
  for (let i = 0; i < user[key].length; i += 1) {
    result[index].children.push({
      data: [
        {
          role: true,
          text: user[key][i].role,
        },
      ],
      text: `${user[key][i].role}@${user[key][i].db}`,
      icon: 'fa fa-bars',
      children: true,
    });
  }
};

UserManagementTree.prototype = {
  init() {
    Notification.start('#btnRefreshUsers');

    const chckRunOnAdminDB = $('#aRunOnAdminDBToFetchUsers');
    chckRunOnAdminDB.iCheck({
      checkboxClass: 'icheckbox_square-green',
    });

    chckRunOnAdminDB.iCheck('uncheck');
    this.initUserTree();
  },

  initUserTree() {
    this.defaultInformationText = Helper.translate({ key: 'user_management_default_tree_text' });
    SessionManager.set(SessionManager.strSessionUsermanagementInfo, '');
    SessionManager.set(SessionManager.strSessionSelectionUserManagement, this.defaultInformationText);
    $('#btnEditUser').hide();
    $('#btnManageUsers').hide();
    $('#btnManageRoles').hide();

    const connection = ReactivityProvider.findOne(ReactivityProvider.types.Connections, { _id: SessionManager.get(SessionManager.strSessionConnection)._id });
    const command = {
      usersInfo: 1,
      showCredentials: true,
    };

    const runOnAdminDB = $('#aRunOnAdminDBToFetchUsers').iCheck('update')[0].checked;
    const self = this;
    Communicator.call({
      methodName: 'command',
      args: { command, runOnAdminDB },
      callback: (err, result) => {
        if (err || result.error) ErrorHandler.showMeteorFuncError(err, result);
        else {
          const dbName = runOnAdminDB ? 'admin' : connection.databaseName;
          const children = this.populateTreeChildrenForUsers(result.result.users);
          const finalObject = {
            core: {
              data(node, callback) {
                if (node.id === '#') {
                  callback([
                    {
                      text: dbName,
                      icon: 'fa fa-database',
                      data: [{ db: true }],
                      state: {
                        opened: true,
                      },
                      children,
                    },
                  ]);
                } else if (node.data[0].user) {
                  const userInfoCommand = {
                    usersInfo: { user: node.text, db: dbName },
                    showCredentials: true,
                    showPrivileges: true,
                  };

                  Communicator.call({
                    methodName: 'command',
                    args: { command: userInfoCommand, runOnAdminDB },
                    callback: (userInfoCommandError, userInfoCommandResult) => {
                      if (userInfoCommandError || userInfoCommandResult.error) ErrorHandler.showMeteorFuncError(userInfoCommandError, userInfoCommandResult);
                      else callback(self.populateTreeChildrenForRoles(userInfoCommandResult.result.users[0]));
                    }
                  });
                } else if (node.data[0].role) {
                  const roleInfoCommand = {
                    rolesInfo: { role: node.data[0].text, db: dbName },
                    showPrivileges: true,
                    showBuiltinRoles: true,
                  };

                  Communicator.call({
                    methodName: 'command',
                    args: { command: roleInfoCommand, runOnAdminDB },
                    callback: (roleInfoCommandError, roleInfoCommandResult) => {
                      if (roleInfoCommandError || roleInfoCommandResult.error) ErrorHandler.showMeteorFuncError(roleInfoCommandError, roleInfoCommandResult);
                      else callback(self.populateTreeChildrenForPrivileges(roleInfoCommandResult.result.roles[0]));
                    }
                  });
                }
              },
            },
          };

          const tree = $('#userTree');
          tree.jstree(finalObject);

          tree.bind('select_node.jstree', (evt, data) => {
            $('#btnEditUser').hide();
            $('#btnManageUsers').hide();
            $('#btnManageRoles').hide();

            if (this.loading) {
              tree.jstree(true).deselect_node(data.node);
              return;
            }

            const node = data.instance.get_node(data.selected[0]);
            if (node.text === SessionManager.get(SessionManager.strSessionSelectionUserManagement)) return;

            // clear texts
            SessionManager.set(SessionManager.strSessionUsermanagementInfo, '');
            SessionManager.set(SessionManager.strSessionSelectionUserManagement, this.defaultInformationText);

            SessionManager.set(SessionManager.strSessionSelectionUserManagement, this.getNodeInformation(node));
          });
          Notification.stop();
        }
      }
    });
  },

  getNodeInformation(node) {
    if (!node.data || node.data[0].db || node.data[0].user) {
      if (!node.data || !node.data[0]) return this.defaultInformationText;

      if (node.data[0].user) {
        SessionManager.set(SessionManager.strSessionUsermanagementManageSelection, node.text);
        $('#btnEditUser').show();
      } else if (node.data[0].db) {
        SessionManager.set(SessionManager.strSessionUsermanagementManageSelection, node.text);
        $('#btnManageUsers').show();
        $('#btnManageRoles').show();
      }

      return this.defaultInformationText;
    }

    if (node.data[0].role) {
      SessionManager.set(SessionManager.strSessionUsermanagementManageSelection, node.data[0].text);
      this.getRoleInfo(node.data[0].text);
    } else if (node.data[0].privilege) this.getResourceInfo(node.data[0].privilegeType);
    else if (node.data[0].action) this.getActionInfo(node.text);

    return node.text;
  },

  getActionInfo(action) {
    Notification.start('#btnRefreshUsers');
    this.loading = true;

    Communicator.call({
      methodName: 'getActionInfo',
      args: { action },
      callback: (err, result) => {
        if (err) SessionManager.set(SessionManager.strSessionUsermanagementInfo, err.message);
        else SessionManager.set(SessionManager.strSessionUsermanagementInfo, result);
        this.loading = false;
        Notification.stop();
      }
    });
  },

  getResourceInfo(resourceType) {
    Notification.start('#btnRefreshUsers');
    this.loading = true;

    Communicator.call({
      methodName: 'getResourceInfo',
      args: { resource: resourceType },
      callback: (err, result) => {
        if (err) SessionManager.set(SessionManager.strSessionUsermanagementInfo, err.message);
        else SessionManager.set(SessionManager.strSessionUsermanagementInfo, result);

        this.loading = false;
        Notification.stop();
      }
    });
  },

  getRoleInfo(role) {
    Notification.start('#btnRefreshUsers');
    this.loading = true;

    Communicator.call({
      methodName: 'getRoleInfo',
      args: { roleName: role },
      callback: (err, result) => {
        if (err) SessionManager.set(SessionManager.strSessionUsermanagementInfo, err.message);
        else SessionManager.set(SessionManager.strSessionUsermanagementInfo, result);

        this.loading = false;
        Notification.stop();
      }
    });
  },

  populateTreeChildrenForPrivileges(role) {
    if (!role) return [];

    const result = [];
    result.push({
      text: 'Privileges',
      data: [{
        isBuiltin: role.isBuiltin,
      }],
      icon: 'fa fa-list-ul',
      children: [],
    });
    result.push({
      text: 'Inherited Privileges',
      data: [{
        isBuiltin: role.isBuiltin,
      }],
      icon: 'fa fa-list-ul',
      children: [],
    });

    if (role.privileges) populatePrivileges.call(this, result, role, 'privileges', 0);
    if (role.inheritedPrivileges) populatePrivileges.call(this, result, role, 'inheritedPrivileges', 1);

    return result;
  },

  getPrivilegeActions(actions) {
    if (!actions) return [];

    const result = [];
    for (let i = 0; i < actions.length; i += 1) {
      result.push({
        data: [
          {
            action: true,
          },
        ],
        text: actions[i],
        icon: 'fa fa-bolt',
        children: false,
      });
    }

    return result;
  },

  getPrivilegeType(resource) {
    if (!resource) return '';
    if (resource.anyResource) return 'anyResource';
    if (resource.cluster) return 'cluster';
    if (resource.db && resource.collection) return 'db+collection';
    if (resource.db) return 'db';
    if (resource.collection) return 'collection';

    return 'non-system';
  },

  getPrivilegeText(resource) {
    if (!resource) return '';

    const type = this.getPrivilegeType(resource);

    if (type === 'db+collection') return `${resource.db} ${resource.collection}`;
    if (type === 'db') return resource.db;
    if (type === 'collection') return resource.collection;
    if (type === 'non-system') return 'all non-system collections';

    return type;
  },

  populateTreeChildrenForRoles(user) {
    if (!user) {
      return [];
    }
    const result = [];
    result.push({
      text: 'Roles',
      icon: 'fa fa-list-alt',
      children: [],
    });
    result.push({
      text: 'Inherited Roles',
      icon: 'fa fa-list-alt',
      children: [],
    });

    if (user.roles) populateRoles(result, user, 'roles', 0);
    if (user.inheritedRoles) populateRoles(result, user, 'inheritedRoles', 1);

    return result;
  },

  populateTreeChildrenForUsers(users) {
    const result = [];
    for (let i = 0; i < users.length; i += 1) {
      result.push({
        id: users[i]._id,
        text: users[i].user,
        icon: 'fa fa-user',
        data: [
          {
            user: true,
          },
        ],
        children: true,
      });
    }

    return result;
  }
};

export default new UserManagementTree();
<commit_msg>refactoring<commit_after>import { Communicator, ReactivityProvider } from '/client/imports/facades';
import { Notification, ErrorHandler, SessionManager } from '/client/imports/modules';
import Helper from '/client/imports/helpers/helper';

const UserManagementTree = function () {
  this.loading = false;
  this.defaultInformationText = '';
};

const populatePrivileges = function (result, role, key, index) {
  for (let i = 0; i < role[key].length; i += 1) {
    result[index].children.push({
      data: [
        {
          privilege: true,
          privilegeType: this.getPrivilegeType(role[key][i].resource),
        }
      ],
      text: this.getPrivilegeText(role[key][i].resource),
      icon: 'fa fa-gears',
      children: this.getPrivilegeActions(role[key][i].actions),
    });
  }
};

const populateRoles = function (result, user, key, index) {
  for (let i = 0; i < user[key].length; i += 1) {
    result[index].children.push({
      data: [
        {
          role: true,
          text: user[key][i].role,
        },
      ],
      text: `${user[key][i].role}@${user[key][i].db}`,
      icon: 'fa fa-bars',
      children: true,
    });
  }
};

const getInfo = function (args, methodName) {
  Notification.start('#btnRefreshUsers');
  this.loading = true;

  Communicator.call({
    methodName,
    args,
    callback: (err, result) => {
      if (err) SessionManager.set(SessionManager.strSessionUsermanagementInfo, err.message);
      else SessionManager.set(SessionManager.strSessionUsermanagementInfo, result);

      this.loading = false;
      Notification.stop();
    }
  });
};

UserManagementTree.prototype = {
  init() {
    Notification.start('#btnRefreshUsers');

    const chckRunOnAdminDB = $('#aRunOnAdminDBToFetchUsers');
    chckRunOnAdminDB.iCheck({
      checkboxClass: 'icheckbox_square-green',
    });

    chckRunOnAdminDB.iCheck('uncheck');
    this.initUserTree();
  },

  initUserTree() {
    this.defaultInformationText = Helper.translate({ key: 'user_management_default_tree_text' });
    SessionManager.set(SessionManager.strSessionUsermanagementInfo, '');
    SessionManager.set(SessionManager.strSessionSelectionUserManagement, this.defaultInformationText);
    $('#btnEditUser').hide();
    $('#btnManageUsers').hide();
    $('#btnManageRoles').hide();

    const connection = ReactivityProvider.findOne(ReactivityProvider.types.Connections, { _id: SessionManager.get(SessionManager.strSessionConnection)._id });
    const command = {
      usersInfo: 1,
      showCredentials: true,
    };

    const runOnAdminDB = $('#aRunOnAdminDBToFetchUsers').iCheck('update')[0].checked;
    const self = this;
    Communicator.call({
      methodName: 'command',
      args: { command, runOnAdminDB },
      callback: (err, result) => {
        if (err || result.error) ErrorHandler.showMeteorFuncError(err, result);
        else {
          const dbName = runOnAdminDB ? 'admin' : connection.databaseName;
          const children = this.populateTreeChildrenForUsers(result.result.users);
          const finalObject = {
            core: {
              data(node, callback) {
                if (node.id === '#') {
                  callback([
                    {
                      text: dbName,
                      icon: 'fa fa-database',
                      data: [{ db: true }],
                      state: {
                        opened: true,
                      },
                      children,
                    },
                  ]);
                } else if (node.data[0].user) {
                  const userInfoCommand = {
                    usersInfo: { user: node.text, db: dbName },
                    showCredentials: true,
                    showPrivileges: true,
                  };

                  Communicator.call({
                    methodName: 'command',
                    args: { command: userInfoCommand, runOnAdminDB },
                    callback: (userInfoCommandError, userInfoCommandResult) => {
                      if (userInfoCommandError || userInfoCommandResult.error) ErrorHandler.showMeteorFuncError(userInfoCommandError, userInfoCommandResult);
                      else callback(self.populateTreeChildrenForRoles(userInfoCommandResult.result.users[0]));
                    }
                  });
                } else if (node.data[0].role) {
                  const roleInfoCommand = {
                    rolesInfo: { role: node.data[0].text, db: dbName },
                    showPrivileges: true,
                    showBuiltinRoles: true,
                  };

                  Communicator.call({
                    methodName: 'command',
                    args: { command: roleInfoCommand, runOnAdminDB },
                    callback: (roleInfoCommandError, roleInfoCommandResult) => {
                      if (roleInfoCommandError || roleInfoCommandResult.error) ErrorHandler.showMeteorFuncError(roleInfoCommandError, roleInfoCommandResult);
                      else callback(self.populateTreeChildrenForPrivileges(roleInfoCommandResult.result.roles[0]));
                    }
                  });
                }
              },
            },
          };

          const tree = $('#userTree');
          tree.jstree(finalObject);

          tree.bind('select_node.jstree', (evt, data) => {
            $('#btnEditUser').hide();
            $('#btnManageUsers').hide();
            $('#btnManageRoles').hide();

            if (this.loading) {
              tree.jstree(true).deselect_node(data.node);
              return;
            }

            const node = data.instance.get_node(data.selected[0]);
            if (node.text === SessionManager.get(SessionManager.strSessionSelectionUserManagement)) return;

            // clear texts
            SessionManager.set(SessionManager.strSessionUsermanagementInfo, '');
            SessionManager.set(SessionManager.strSessionSelectionUserManagement, this.defaultInformationText);

            SessionManager.set(SessionManager.strSessionSelectionUserManagement, this.getNodeInformation(node));
          });
          Notification.stop();
        }
      }
    });
  },

  getNodeInformation(node) {
    if (!node.data || node.data[0].db || node.data[0].user) {
      if (!node.data || !node.data[0]) return this.defaultInformationText;

      if (node.data[0].user) {
        SessionManager.set(SessionManager.strSessionUsermanagementManageSelection, node.text);
        $('#btnEditUser').show();
      } else if (node.data[0].db) {
        SessionManager.set(SessionManager.strSessionUsermanagementManageSelection, node.text);
        $('#btnManageUsers').show();
        $('#btnManageRoles').show();
      }

      return this.defaultInformationText;
    }

    if (node.data[0].role) {
      SessionManager.set(SessionManager.strSessionUsermanagementManageSelection, node.data[0].text);
      this.getRoleInfo(node.data[0].text);
    } else if (node.data[0].privilege) this.getResourceInfo(node.data[0].privilegeType);
    else if (node.data[0].action) this.getActionInfo(node.text);

    return node.text;
  },

  getActionInfo(action) {
    Notification.start('#btnRefreshUsers');
    this.loading = true;

    Communicator.call({
      methodName: 'getActionInfo',
      args: { action },
      callback: (err, result) => {
        if (err) SessionManager.set(SessionManager.strSessionUsermanagementInfo, err.message);
        else SessionManager.set(SessionManager.strSessionUsermanagementInfo, result);
        this.loading = false;
        Notification.stop();
      }
    });
  },

  getResourceInfo(resourceType) {
    getInfo.call(this, { resource: resourceType }, 'getResourceInfo');
  },

  getRoleInfo(role) {
    getInfo.call(this, { roleName: role }, 'getRoleInfo');
  },

  populateTreeChildrenForPrivileges(role) {
    if (!role) return [];

    const result = [];
    result.push({
      text: 'Privileges',
      data: [{
        isBuiltin: role.isBuiltin,
      }],
      icon: 'fa fa-list-ul',
      children: [],
    });
    result.push({
      text: 'Inherited Privileges',
      data: [{
        isBuiltin: role.isBuiltin,
      }],
      icon: 'fa fa-list-ul',
      children: [],
    });

    if (role.privileges) populatePrivileges.call(this, result, role, 'privileges', 0);
    if (role.inheritedPrivileges) populatePrivileges.call(this, result, role, 'inheritedPrivileges', 1);

    return result;
  },

  getPrivilegeActions(actions) {
    if (!actions) return [];

    const result = [];
    for (let i = 0; i < actions.length; i += 1) {
      result.push({
        data: [
          {
            action: true,
          },
        ],
        text: actions[i],
        icon: 'fa fa-bolt',
        children: false,
      });
    }

    return result;
  },

  getPrivilegeType(resource) {
    if (!resource) return '';
    if (resource.anyResource) return 'anyResource';
    if (resource.cluster) return 'cluster';
    if (resource.db && resource.collection) return 'db+collection';
    if (resource.db) return 'db';
    if (resource.collection) return 'collection';

    return 'non-system';
  },

  getPrivilegeText(resource) {
    if (!resource) return '';

    const type = this.getPrivilegeType(resource);

    if (type === 'db+collection') return `${resource.db} ${resource.collection}`;
    if (type === 'db') return resource.db;
    if (type === 'collection') return resource.collection;
    if (type === 'non-system') return 'all non-system collections';

    return type;
  },

  populateTreeChildrenForRoles(user) {
    if (!user) {
      return [];
    }
    const result = [];
    result.push({
      text: 'Roles',
      icon: 'fa fa-list-alt',
      children: [],
    });
    result.push({
      text: 'Inherited Roles',
      icon: 'fa fa-list-alt',
      children: [],
    });

    if (user.roles) populateRoles(result, user, 'roles', 0);
    if (user.inheritedRoles) populateRoles(result, user, 'inheritedRoles', 1);

    return result;
  },

  populateTreeChildrenForUsers(users) {
    const result = [];
    for (let i = 0; i < users.length; i += 1) {
      result.push({
        id: users[i]._id,
        text: users[i].user,
        icon: 'fa fa-user',
        data: [
          {
            user: true,
          },
        ],
        children: true,
      });
    }

    return result;
  }
};

export default new UserManagementTree();
<|endoftext|>


<commit_before>define(['marionette', 'collections/users'], function(Marionette, Users) {

    var UserItem = Marionette.ItemView.extend({
        tagName: 'li',
        template: _.template('<%=FULLNAME%> - <% if (LAST) { %><%=VISITS%> Visits (Last Visit: <%=LAST%>)<% } else { %>*NEW*<% } %>'),
        className: function() {
            return this.model.get('VISITS') == 0 ? 'new' : ''
        },
    })

    var LoadingView = Marionette.ItemView.extend({
        tagName: 'li',
        template: _.template('')
    })

    return Marionette.CollectionView.extend({
        template: _.template('
Users

'),
        childViewContainer: '.users',
        childView: UserItem,
        emptyView: LoadingView,
        className: 'visit_users',

        initialize: function(options) {
            this.collection = new Users(null, { visit: options.visit })
            this.collection.fetch()
        }
    })

})<commit_msg>fix users template<commit_after>define(['marionette', 'collections/users'], function(Marionette, Users) {

    var UserItem = Marionette.ItemView.extend({
        tagName: 'li',
        template: _.template('<%=FULLNAME%> - <% if (LAST) { %><%=VISITS%> Visits (Last Visit: <%=LAST%>)<% } else { %>*NEW*<% } %>'),
        className: function() {
            return this.model.get('VISITS') == 0 ? 'new' : ''
        },
    })

    var LoadingView = Marionette.ItemView.extend({
        tagName: 'li',
        template: _.template('')
    })

    return Marionette.CollectionView.extend({
        //template: _.template('
Users

'),
        //childViewContainer: '.users',
        tagName: 'ul',
        childView: UserItem,
        emptyView: LoadingView,
        className: 'visit_users',

        initialize: function(options) {
            this.collection = new Users(null, { visit: options.visit })
            this.collection.fetch()
        }
    })

})<|endoftext|>


<commit_before>define(['marionette', 'utils', 'backbone-validation'], function(Marionette, utils) {

    return Marionette.ItemView.extend({
        template: false,
        tagName: 'canvas',
        className: 'plate',

        collectionEvents: {
            'change reset': 'drawPlate',
        },

        events: {
            'mousemove': 'hoverDrop',
            'click': 'clickDrop',
        },

        hoverDrop: function(e) {
            var hover = this._xy_to_drop(utils.get_xy(e,this.$el))
            if (hover != this.hover) {
                this.hover = hover
                this.drawPlate()
            }

        },

        clickDrop: function(e) {
            e.preventDefault()
            var pos = this._xy_to_drop(utils.get_xy(e,this.$el))
            if (pos) {
                var drop = this.collection.findWhere({ LOCATION: pos.toString() })

                if (drop) drop.set('isSelected', true)
                this.drawPlate()
            }
        },

        initialize: function(options) {
            this.pt = this.getOption('type')
            this.inspectionimages = options && options.inspectionimages
            if (this.inspectionimages) this.listenTo(this.inspectionimages, 'sync', this.render, this)

            this.hover = {}
            this.showImageStatus = this.getOption('showImageStatus')
            this.showSampleStatus = this.getOption('showSampleStatus')

            Backbone.Validation.bind(this, {
                collection: this.collection
            });
        },

        setInspectionImages: function(imgs) {
            this.inspectionimages = imgs
            this.showImageStatus = true
            if (this.inspectionimages) this.listenTo(this.inspectionimages, 'sync', this.render, this)
        },

        setShowSampleStatus: function(status) {
            this.showSampleStatus = status
            this.showImageStatus = !status
            this.drawPlate()
        },

        onDomRefresh: function() {
            this.canvas = this.$el[0]
            this.ctx = this.canvas.getContext('2d')

            this.canvas.width = this.$el.parent().width()
            this.canvas.height = this.canvas.width*0.68
            console.log('type', this.getOption('type'), this.canvas, this.ctx)
            this.pt.setGeometry(this.canvas.width, this.canvas.height)
            this.drawPlate()

            //$(document).unbind('keydown', this.keyPress)
            //$(document).bind('keydown', this.keyPress.bind(this))
            $(document).unbind('keydown').bind('keydown', this.keyPress.bind(this))
        },

        keyPress: function(e) {
            if ($(e.target).is('input') || $(e.target).is('select') || $(e.target).is('textarea')) return

            var current = this.collection.findWhere({ isSelected: true })
            var pos = parseInt(current.get('LOCATION'))

            if (e.which == 37) {
                e.preventDefault()
                pos--

            } else if (e.which == 39) {
                e.preventDefault()
                pos++

            } else if (e.which == 38) {
                e.preventDefault()
                pos -= this.pt.get('well_per_row')*this.pt.dropTotal()

            } else if (e.which == 40) {
                e.preventDefault()
                pos += this.pt.get('well_per_row')*this.pt.dropTotal()
            }

            var n = this.collection.findWhere({ LOCATION: pos.toString() })
            //console.log(pos, n)
            if (n) {
                n.set('isSelected', true)
                this.drawPlate()
            }
        },

        onDestroy: function() {
            console.log('destroy plate')
            //$(document).unbind('keydown', this.keyPress.bind(this))
            $(document).unbind('keydown')
        },

        setType: function(type) {
            this.pt = type
            this.pt.setGeometry(this.canvas.width, this.canvas.height)
            this.drawPlate()
        },

        // Draw plate
        drawPlate: function() {
            console.log('draw plate')
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)

            // Plate labels
            for (var x = 0; x < this.pt.get('well_per_row'); x++) {
                this.ctx.fillStyle = '#000000'
                this.ctx.font = (this.canvas.width > 500 ? 18 : 14) +"px Arial"
                this.ctx.lineWidth = 1
                this.ctx.fillText(x+1,this.pt.get('offset_x')+x*(this.pt.get('well_width')+this.pt.get('well_pad')),20);
            }

            for (var y = 0; y < this.pt.wellTotal()/this.pt.get('well_per_row'); y++) {
                this.ctx.fillStyle = '#000'
                this.ctx.font = (this.canvas.width > 500 ? 18 : 14) +"px Arial"
                this.ctx.lineWidth = 1
                var off = this.canvas.width > 500 ? 26 : 15
                this.ctx.fillText(String.fromCharCode(y+65),0,off+this.pt.get('offset_y')+y*(this.pt.get('well_height')+this.pt.get('well_pad')));
            }

            for (var i = 0; i < this.pt.wellTotal(); i++) {
                var row = i % this.pt.get('well_per_row')
                var col = Math.floor(i / this.pt.get('well_per_row'))

                this.ctx.beginPath()
                this.ctx.strokeStyle = '#000'
                this.ctx.rect(this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad')), this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad')), this.pt.get('well_width'), this.pt.get('well_height'))

                this.ctx.lineWidth = 1;
                this.ctx.strokeStyle = '#000'
                this.ctx.stroke()

                for (var j = 0; j < this.pt.get('drop_per_well_x'); j++) {
                    for (var k = 0; k < this.pt.get('drop_per_well_y'); k++) {
                        var did = (k*this.pt.get('drop_per_well_x'))+j
                        if (this.pt.get('well_drop') > -1) {
                            if (did == this.pt.get('well_drop')) continue
                                if (did > this.pt.get('well_drop')) did--;
                        }

                        var sampleid = i*this.pt.dropTotal()+did+1
                        var sample = this.collection.findWhere({ LOCATION: sampleid.toString() })

                        if (sample && this.showImageStatus && this.inspectionimages) var im = this.inspectionimages.findWhere({ BLSAMPLEID: sample.get('BLSAMPLEID') })
                        else var im = null

                        this.ctx.beginPath()
                        this.ctx.lineWidth = 1;
                        if (sample && sample.get('isSelected')) {
                            this.ctx.strokeStyle = 'cyan'

                        } else if (sample && sample.get('PROTEINID') > -1) {
                            if (this.showImageStatus) {
                                if (im) {
                                    if (im.urlFor('full') in app.imagecache) this.ctx.strokeStyle = '#000'
                                    else this.ctx.strokeStyle = '#aaa'
                                } else this.ctx.strokeStyle = '#ddd'

                            } else this.ctx.strokeStyle = '#000'

                        } else this.ctx.strokeStyle = '#ddd'

                        this.ctx.rect(this.pt.get('drop_offset_x')+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y')+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')), this.pt.get('drop_widthpx'), this.pt.get('drop_heightpx'))

                        // Highlight Hovered Sample
                        if (this.hover == sampleid) {
                            this.ctx.fillStyle = '#cccccc'
                            this.ctx.fill()
                        }

                        // Highlight Selected Sample
                        if (sample && sample.get('isSelected')) {
                            this.ctx.fillStyle = '#dddddd'
                            this.ctx.fill()
                        }

                        // Show if drop is valid
                        if (sample && this.getOption('showValid')) {
                            if (sample.get('PROTEINID') > -1) {
                                this.ctx.fillStyle = sample.isValid(true) ? '#82d180' : '#f26c4f'
                                this.ctx.fill()
                            }
                        }

                        // Show status
                        if (sample && this.getOption('showStatus')) {
                            var colors = {
                                SC: '#fdfd96',
                                AI: '#ffb347',
                                DC: '#87ceeb',
                                AP: '#77dd77',
                            }

                            _.each(colors, function(v,t) {
                                if (sample.get(t) > 0) this.ctx.fillStyle = v
                            }, this)
                        }

                        // Show image score
                        if (sample && this.showImageStatus) {
                            if (im) {
                                var isc = im.get('SCORECOLOUR')
                                if (isc){
                                    this.ctx.fillStyle = isc
                                    this.ctx.fill()
                                }
                            }

                        }

                        this.ctx.stroke()

                        // Sample number
                        if (this.canvas.width > 400 && sample && sample.get('PROTEINID') > -1) {
                            this.ctx.fillStyle = '#000'
                            this.ctx.font = "8px Arial"
                            this.ctx.lineWidth = 1
                            this.ctx.fillText(sampleid,this.pt.get('drop_offset_x')+2+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y')+10+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')));
                        }
                    }
                }
            }
        },

        // Convert xy position to sample id
         _xy_to_drop: function(cur) {
            var x = Math.floor((cur[0] - this.pt.get('offset_x'))/(this.pt.get('well_width')+this.pt.get('well_pad')))
            var y = Math.floor((cur[1] - this.pt.get('offset_y'))/(this.pt.get('well_height')+this.pt.get('well_pad')))

            var wox = cur[0] - this.pt.get('drop_offset_x') - this.pt.get('offset_x') - this.pt.get('drop_pad') - x*(this.pt.get('well_width')+this.pt.get('well_pad'))
            var woy = cur[1] - this.pt.get('drop_offset_y') - this.pt.get('offset_y') - this.pt.get('drop_pad') - y*(this.pt.get('well_height')+this.pt.get('well_pad'))

            if (wox > 0 && wox < this.pt.get('drop_per_well_x')*this.pt.get('drop_widthpx') && woy > 0 && woy < this.pt.get('drop_per_well_y')*this.pt.get('drop_heightpx')) {
                var dx = Math.floor(wox / this.pt.get('drop_widthpx'))
                var dy = Math.floor(woy / this.pt.get('drop_heightpx'))
                var did = dy*this.pt.get('drop_per_well_x')+dx

                if (this.pt.get('well_drop') != did) {
                    // skip over drop that is well
                    if (this.pt.get('well_drop') > -1 && did > this.pt.get('well_drop')) did--

                    if (did < this.pt.dropTotal()) {
                        return did + (x+y*this.pt.get('well_per_row'))*this.pt.dropTotal() + 1
                    }
                }
            }
        }

    })

})<commit_msg>actually fill sample color<commit_after>define(['marionette', 'utils', 'backbone-validation'], function(Marionette, utils) {

    return Marionette.ItemView.extend({
        template: false,
        tagName: 'canvas',
        className: 'plate',

        collectionEvents: {
            'change reset': 'drawPlate',
        },

        events: {
            'mousemove': 'hoverDrop',
            'click': 'clickDrop',
        },

        hoverDrop: function(e) {
            var hover = this._xy_to_drop(utils.get_xy(e,this.$el))
            if (hover != this.hover) {
                this.hover = hover
                this.drawPlate()
            }

        },

        clickDrop: function(e) {
            e.preventDefault()
            var pos = this._xy_to_drop(utils.get_xy(e,this.$el))
            if (pos) {
                var drop = this.collection.findWhere({ LOCATION: pos.toString() })

                if (drop) drop.set('isSelected', true)
                this.drawPlate()
            }
        },

        initialize: function(options) {
            this.pt = this.getOption('type')
            this.inspectionimages = options && options.inspectionimages
            if (this.inspectionimages) this.listenTo(this.inspectionimages, 'sync', this.render, this)

            this.hover = {}
            this.showImageStatus = this.getOption('showImageStatus')
            this.showSampleStatus = this.getOption('showSampleStatus')

            Backbone.Validation.bind(this, {
                collection: this.collection
            });
        },

        setInspectionImages: function(imgs) {
            this.inspectionimages = imgs
            this.showImageStatus = true
            if (this.inspectionimages) this.listenTo(this.inspectionimages, 'sync', this.render, this)
        },

        setShowSampleStatus: function(status) {
            this.showSampleStatus = status
            this.showImageStatus = !status
            this.drawPlate()
        },

        onDomRefresh: function() {
            this.canvas = this.$el[0]
            this.ctx = this.canvas.getContext('2d')

            this.canvas.width = this.$el.parent().width()
            this.canvas.height = this.canvas.width*0.68
            console.log('type', this.getOption('type'), this.canvas, this.ctx)
            this.pt.setGeometry(this.canvas.width, this.canvas.height)
            this.drawPlate()

            //$(document).unbind('keydown', this.keyPress)
            //$(document).bind('keydown', this.keyPress.bind(this))
            $(document).unbind('keydown').bind('keydown', this.keyPress.bind(this))
        },

        keyPress: function(e) {
            if ($(e.target).is('input') || $(e.target).is('select') || $(e.target).is('textarea')) return

            var current = this.collection.findWhere({ isSelected: true })
            var pos = parseInt(current.get('LOCATION'))

            if (e.which == 37) {
                e.preventDefault()
                pos--

            } else if (e.which == 39) {
                e.preventDefault()
                pos++

            } else if (e.which == 38) {
                e.preventDefault()
                pos -= this.pt.get('well_per_row')*this.pt.dropTotal()

            } else if (e.which == 40) {
                e.preventDefault()
                pos += this.pt.get('well_per_row')*this.pt.dropTotal()
            }

            var n = this.collection.findWhere({ LOCATION: pos.toString() })
            //console.log(pos, n)
            if (n) {
                n.set('isSelected', true)
                this.drawPlate()
            }
        },

        onDestroy: function() {
            console.log('destroy plate')
            //$(document).unbind('keydown', this.keyPress.bind(this))
            $(document).unbind('keydown')
        },

        setType: function(type) {
            this.pt = type
            this.pt.setGeometry(this.canvas.width, this.canvas.height)
            this.drawPlate()
        },

        // Draw plate
        drawPlate: function() {
            console.log('draw plate')
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)

            // Plate labels
            for (var x = 0; x < this.pt.get('well_per_row'); x++) {
                this.ctx.fillStyle = '#000000'
                this.ctx.font = (this.canvas.width > 500 ? 18 : 14) +"px Arial"
                this.ctx.lineWidth = 1
                this.ctx.fillText(x+1,this.pt.get('offset_x')+x*(this.pt.get('well_width')+this.pt.get('well_pad')),20);
            }

            for (var y = 0; y < this.pt.wellTotal()/this.pt.get('well_per_row'); y++) {
                this.ctx.fillStyle = '#000'
                this.ctx.font = (this.canvas.width > 500 ? 18 : 14) +"px Arial"
                this.ctx.lineWidth = 1
                var off = this.canvas.width > 500 ? 26 : 15
                this.ctx.fillText(String.fromCharCode(y+65),0,off+this.pt.get('offset_y')+y*(this.pt.get('well_height')+this.pt.get('well_pad')));
            }

            for (var i = 0; i < this.pt.wellTotal(); i++) {
                var row = i % this.pt.get('well_per_row')
                var col = Math.floor(i / this.pt.get('well_per_row'))

                this.ctx.beginPath()
                this.ctx.strokeStyle = '#000'
                this.ctx.rect(this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad')), this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad')), this.pt.get('well_width'), this.pt.get('well_height'))

                this.ctx.lineWidth = 1;
                this.ctx.strokeStyle = '#000'
                this.ctx.stroke()

                for (var j = 0; j < this.pt.get('drop_per_well_x'); j++) {
                    for (var k = 0; k < this.pt.get('drop_per_well_y'); k++) {
                        var did = (k*this.pt.get('drop_per_well_x'))+j
                        if (this.pt.get('well_drop') > -1) {
                            if (did == this.pt.get('well_drop')) continue
                                if (did > this.pt.get('well_drop')) did--;
                        }

                        var sampleid = i*this.pt.dropTotal()+did+1
                        var sample = this.collection.findWhere({ LOCATION: sampleid.toString() })

                        if (sample && this.showImageStatus && this.inspectionimages) var im = this.inspectionimages.findWhere({ BLSAMPLEID: sample.get('BLSAMPLEID') })
                        else var im = null

                        this.ctx.beginPath()
                        this.ctx.lineWidth = 1;
                        if (sample && sample.get('isSelected')) {
                            this.ctx.strokeStyle = 'cyan'

                        } else if (sample && sample.get('PROTEINID') > -1) {
                            if (this.showImageStatus) {
                                if (im) {
                                    if (im.urlFor('full') in app.imagecache) this.ctx.strokeStyle = '#000'
                                    else this.ctx.strokeStyle = '#aaa'
                                } else this.ctx.strokeStyle = '#ddd'

                            } else this.ctx.strokeStyle = '#000'

                        } else this.ctx.strokeStyle = '#ddd'

                        this.ctx.rect(this.pt.get('drop_offset_x')+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y')+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')), this.pt.get('drop_widthpx'), this.pt.get('drop_heightpx'))

                        // Highlight Hovered Sample
                        if (this.hover == sampleid) {
                            this.ctx.fillStyle = '#cccccc'
                            this.ctx.fill()
                        }

                        // Highlight Selected Sample
                        if (sample && sample.get('isSelected')) {
                            this.ctx.fillStyle = '#dddddd'
                            this.ctx.fill()
                        }

                        // Show if drop is valid
                        if (sample && this.getOption('showValid')) {
                            if (sample.get('PROTEINID') > -1) {
                                this.ctx.fillStyle = sample.isValid(true) ? '#82d180' : '#f26c4f'
                                this.ctx.fill()
                            }
                        }

                        // Show status
                        if (sample && this.showSampleStatus) {
                            var colors = {
                                SC: '#fdfd96',
                                AI: '#ffb347',
                                DC: '#87ceeb',
                                AP: '#77dd77',
                            }

                            var hasStatus = false
                            _.each(colors, function(v,t) {
                                if (sample.get(t) > 0) {
                                    this.ctx.fillStyle = v
                                    hasStatus = true
                                }
                            }, this)
                            if (hasStatus) this.ctx.fill()
                        }

                        // Show image score
                        if (sample && this.showImageStatus) {
                            if (im) {
                                var isc = im.get('SCORECOLOUR')
                                if (isc){
                                    this.ctx.fillStyle = isc
                                    this.ctx.fill()
                                }
                            }

                        }

                        this.ctx.stroke()

                        // Sample number
                        if (this.canvas.width > 400 && sample && sample.get('PROTEINID') > -1) {
                            this.ctx.fillStyle = '#000'
                            this.ctx.font = "8px Arial"
                            this.ctx.lineWidth = 1
                            this.ctx.fillText(sampleid,this.pt.get('drop_offset_x')+2+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y')+10+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')));
                        }
                    }
                }
            }
        },

        // Convert xy position to sample id
         _xy_to_drop: function(cur) {
            var x = Math.floor((cur[0] - this.pt.get('offset_x'))/(this.pt.get('well_width')+this.pt.get('well_pad')))
            var y = Math.floor((cur[1] - this.pt.get('offset_y'))/(this.pt.get('well_height')+this.pt.get('well_pad')))

            var wox = cur[0] - this.pt.get('drop_offset_x') - this.pt.get('offset_x') - this.pt.get('drop_pad') - x*(this.pt.get('well_width')+this.pt.get('well_pad'))
            var woy = cur[1] - this.pt.get('drop_offset_y') - this.pt.get('offset_y') - this.pt.get('drop_pad') - y*(this.pt.get('well_height')+this.pt.get('well_pad'))

            if (wox > 0 && wox < this.pt.get('drop_per_well_x')*this.pt.get('drop_widthpx') && woy > 0 && woy < this.pt.get('drop_per_well_y')*this.pt.get('drop_heightpx')) {
                var dx = Math.floor(wox / this.pt.get('drop_widthpx'))
                var dy = Math.floor(woy / this.pt.get('drop_heightpx'))
                var did = dy*this.pt.get('drop_per_well_x')+dx

                if (this.pt.get('well_drop') != did) {
                    // skip over drop that is well
                    if (this.pt.get('well_drop') > -1 && did > this.pt.get('well_drop')) did--

                    if (did < this.pt.dropTotal()) {
                        return did + (x+y*this.pt.get('well_per_row'))*this.pt.dropTotal() + 1
                    }
                }
            }
        }

    })

})<|endoftext|>


<commit_before>/*
 * This file is part of GPaste.
 *
 * Copyright (c) 2010-2016, Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
 */
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */

const Gettext = imports.gettext;
const Lang = imports.lang;

const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;

const Clutter = imports.gi.Clutter;

const GPaste = imports.gi.GPaste;

const _ = Gettext.domain('GPaste').gettext;

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();

const AboutItem = Me.imports.aboutItem;
const DummyHistoryItem = Me.imports.dummyHistoryItem;
const EmptyHistoryItem = Me.imports.emptyHistoryItem;
const Item = Me.imports.item;
const PageSwitcher = Me.imports.pageSwitcher;
const SearchItem = Me.imports.searchItem;
const StateSwitch = Me.imports.stateSwitch;
const StatusIcon = Me.imports.statusIcon;
const UiItem = Me.imports.uiItem;

const GPasteIndicator = new Lang.Class({
    Name: 'GPasteIndicator',
    Extends: PanelMenu.Button,

    _init: function() {
        this.parent(0.0, "GPaste");

        this._statusIcon = new StatusIcon.GPasteStatusIcon();
        this.actor.add_child(this._statusIcon.actor);

        this._settings = new GPaste.Settings();

        this._headerSize = 0;
        this._postHeaderSize = 0;
        this._history = [];
        this._preFooterSize = 0;
        this._footerSize = 0;

        this._searchResults = [];

        this._dummyHistoryItem = new DummyHistoryItem.GPasteDummyHistoryItem();

        this._searchItem = new SearchItem.GPasteSearchItem();
        this._searchItem.connect('text-changed', Lang.bind(this, this._onNewSearch));

        this._settingsSizeChangedId = this._settings.connect('changed::element-size', Lang.bind(this, this._resetElementSize));
        this._resetElementSize();
        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
        this.menu.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));

        this._pageSwitcher = new PageSwitcher.GPastePageSwitcher();
        this._pageSwitcher.connect('switch', Lang.bind(this, function(sw, page) {
            this._updatePage(page);
        }));

        this._actions = new PopupMenu.PopupBaseMenuItem({
            reactive: false,
            can_focus: false
        });

        this._addToPostHeader(this._dummyHistoryItem);
        this._addToPreFooter(new PopupMenu.PopupSeparatorMenuItem());
        this._addToFooter(this._actions);

        GPaste.Client.new(Lang.bind(this, function (obj, result) {
            this._client = GPaste.Client.new_finish(result);

            this._uiItem = new UiItem.GPasteUiItem(this.menu);
            this._emptyHistoryItem = new EmptyHistoryItem.GPasteEmptyHistoryItem(this._client);
            this._aboutItem = new AboutItem.GPasteAboutItem(this._client, this.menu);
            this._switch = new StateSwitch.GPasteStateSwitch(this._client);

            this._addToHeader(this._switch);
            this._addToHeader(this._searchItem);
            this._addToHeader(this._pageSwitcher);

            this._actions.actor.add(this._uiItem.actor, { expand: true, x_fill: false });
            this._actions.actor.add(this._emptyHistoryItem.actor, { expand: true, x_fill: false });
            this._actions.actor.add(this._aboutItem.actor, { expand: true, x_fill: false });

            this._settingsMaxSizeChangedId = this._settings.connect('changed::max-displayed-history-size', Lang.bind(this, this._resetMaxDisplayedSize));
            this._resetMaxDisplayedSize();

            this._clientUpdateId = this._client.connect('update', Lang.bind(this, this._update));
            this._clientShowId = this._client.connect('show-history', Lang.bind(this, this._popup));
            this._clientTrackingId = this._client.connect('tracking', Lang.bind(this, this._toggle));

            this._onStateChanged (true);

            this.menu.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
            this.menu.actor.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));

            this._destroyed = false;
            this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
        }));
    },

    shutdown: function() {
        this._onStateChanged (false);
        this._onDestroy();
        this.destroy();
    },

    _onKeyPressEvent: function(actor, event) {
        if (event.has_control_modifier()) {
            const nb = parseInt(event.get_key_unicode());
            if (!isNaN(nb) && nb >= 0 && nb <= 9 && nb < this._history.length) {
                this._history[nb].activate();
            }
        } else {
            this._maybeUpdateIndexVisibility(event, true);
        }
    },

    _onKeyReleaseEvent: function(actor, event) {
        this._maybeUpdateIndexVisibility(event, false);
    },

    _maybeUpdateIndexVisibility: function(event, state) {
        const key = event.get_key_symbol();
        if (key == Clutter.KEY_Control_L || key == Clutter.KEY_Control_R) {
            this._updateIndexVisibility(state);
        }
    },

    _updateIndexVisibility: function(state) {
        this._history.slice(0, 10).forEach(function(i) {
            i.showIndex(state);
        });
    },

    _hasSearch: function() {
        return this._searchItem.text.length > 0;
    },

    _onSearch: function(page) {
        if (this._hasSearch()) {
            const search = this._searchItem.text.toLowerCase();

            this._client.search(search, Lang.bind(this, function(client, result) {
                this._searchResults = client.search_finish(result);
                let results = this._searchResults.length;
                const maxSize = this._history.length;

                if (!this._pageSwitcher.updateForSize(results)) {
                    return;
                }

                this._pageSwitcher.setActive(page);
                const offset = this._pageSwitcher.getPageOffset();

                if (results > (maxSize + offset)) {
                    results = (maxSize + offset);
                }

                this._history.slice(0, results - offset).forEach(Lang.bind(this, function(i, index) {
                    i.setIndex(this._searchResults[offset + index]);
                }));

                /* If we had no result, updateForSize would have returned false */
                this._dummyHistoryItem.actor.hide();

                this._history.slice(results - offset, maxSize).forEach(function(i) {
                    i.setIndex(-1);
                });
            }));
        } else {
            this._searchResults = [];
            this._refresh(0);
        }
    },

    _onNewSearch: function() {
        this._onSearch(1);
    },

    _resetElementSize: function() {
        const size = this._settings.get_element_size();
        this._searchItem.resetSize(size/2 + 3);
        this._history.forEach(function(i) {
            i.setTextSize(size);
        });
    },

    _updatePage: function(page) {
        this._pageSwitcher.setActive(page);
        this._refresh(0);
    },

    _resetMaxDisplayedSize: function() {
        const oldSize = this._history.length;
        const newSize = this._settings.get_max_displayed_history_size();
        const elementSize = this._settings.get_element_size();

        this._pageSwitcher.setMaxDisplayedSize(newSize);

        const offset = this._pageSwitcher.getPageOffset();

        if (newSize > oldSize) {
            for (let index = oldSize; index < newSize; ++index) {
                let item = new Item.GPasteItem(this._client, elementSize, index + offset);
                this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize + index);
                this._history[index] = item;
            }
        } else {
            for (let i = newSize; i < oldSize; ++i) {
                this._history.pop().destroy();
            }
        }

        if (offset === 0 || oldSize === 0) {
            this._updatePage(1);
        } else {
            this._updatePage((offset / oldSize) + 1);
        }
    },

    _update: function(client, action, target, position) {
        switch (target) {
        case GPaste.UpdateTarget.ALL:
            this._refresh(0);
            break;
        case GPaste.UpdateTarget.POSITION:
            const offset = this._pageSwitcher.getPageOffset();
            const displayPos = position - offset;
            switch (action) {
            case GPaste.UpdateAction.REPLACE:
                this._history[displayPos].refresh();
                break;
            case GPaste.UpdateAction.REMOVE:
                this._refresh(displayPos);
                break;
            }
            break;
        }
    },

    _refresh: function(resetTextFrom) {
        if (this._searchResults.length > 0) {
            this._onSearch(this._pageSwitcher.getPage());
        } else if (this._hasSearch()) {
            this._history.forEach(function(i, index) {
                i.setIndex(-1);
            });
            this._updateVisibility(true);
            this._dummyHistoryItem.showNoResult();
        } else {
            this._client.get_history_name(Lang.bind(this, function(client, result) {
                const name = client.get_history_name_finish(result);

                this._client.get_history_size(name, Lang.bind(this, function(client, result) {
                    const realSize = client.get_history_size_finish(result);

                    if (!this._pageSwitcher.updateForSize(realSize)) {
                        return;
                    }

                    const maxSize = this._history.length;
                    const offset = this._pageSwitcher.getPageOffset();
                    const size = Math.min(realSize - offset, maxSize);

                    this._history.slice(resetTextFrom, size).forEach(function(i, index) {
                        i.setIndex(offset + index);
                    });
                    this._history.slice(size, maxSize).forEach(function(i, index) {
                        i.setIndex(-1);
                    });

                    this._updateVisibility(size == 0);
                }));
            }));
        }
    },

    _updateVisibility: function(empty) {
        if (empty) {
            this._dummyHistoryItem.showEmpty();
            this._emptyHistoryItem.actor.hide();
            this._searchItem.actor.hide();
        } else {
            this._dummyHistoryItem.actor.hide();
            this._emptyHistoryItem.actor.show();
            this._searchItem.actor.show();
        }
    },

    _popup: function() {
        this.menu.open(true);
        this._selectSearch();
    },

    _toggle: function(c, state) {
        this._switch.toggle(state);
    },

    _selectSearch: function() {
        if (this._history.length > 0) {
            this._searchItem.grabFocus();
        }
    },

    _addToHeader: function(item) {
        this.menu.addMenuItem(item, this._headerSize++);
    },

    _addToPostHeader: function(item) {
        this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize++);
    },

    _addToPreFooter: function(item) {
        this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize + this._history.length + this._preFooterSize++);
    },

    _addToFooter: function(item) {
        this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize + this._history.length + this._preFooterSize + this._footerSize++);
    },

    _onStateChanged: function(state) {
        this._client.on_extension_state_changed(state, null);
    },

    _onOpenStateChanged: function(menu, state) {
        if (state) {
            this._searchItem.reset();
            this._updatePage(1);
        } else {
            this._updateIndexVisibility(false);
        }
    },

    _onMenuKeyPress: function(actor, event) {
        const symbol = event.get_key_symbol();
        if (symbol == Clutter.KEY_Left) {
            return this._pageSwitcher.previous();
        }
        if (symbol == Clutter.KEY_Right) {
            return this._pageSwitcher.next();
        }
        return Clutter.EVENT_PROPAGATE;
    },

    _onDestroy: function() {
        if (this._destroyed) {
            return;
        }
        this._destroyed = true;
        this._client.disconnect(this._clientUpdateId);
        this._client.disconnect(this._clientShowId);
        this._client.disconnect(this._clientTrackingId);
        this._settings.disconnect(this._settingsMaxSizeChangedId);
        this._settings.disconnect(this._settingsSizeChangedId);
    }
});

<commit_msg>gnome-shell: better handling of empty search results<commit_after>/*
 * This file is part of GPaste.
 *
 * Copyright (c) 2010-2016, Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
 */
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */

const Gettext = imports.gettext;
const Lang = imports.lang;

const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;

const Clutter = imports.gi.Clutter;

const GPaste = imports.gi.GPaste;

const _ = Gettext.domain('GPaste').gettext;

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();

const AboutItem = Me.imports.aboutItem;
const DummyHistoryItem = Me.imports.dummyHistoryItem;
const EmptyHistoryItem = Me.imports.emptyHistoryItem;
const Item = Me.imports.item;
const PageSwitcher = Me.imports.pageSwitcher;
const SearchItem = Me.imports.searchItem;
const StateSwitch = Me.imports.stateSwitch;
const StatusIcon = Me.imports.statusIcon;
const UiItem = Me.imports.uiItem;

const GPasteIndicator = new Lang.Class({
    Name: 'GPasteIndicator',
    Extends: PanelMenu.Button,

    _init: function() {
        this.parent(0.0, "GPaste");

        this._statusIcon = new StatusIcon.GPasteStatusIcon();
        this.actor.add_child(this._statusIcon.actor);

        this._settings = new GPaste.Settings();

        this._headerSize = 0;
        this._postHeaderSize = 0;
        this._history = [];
        this._preFooterSize = 0;
        this._footerSize = 0;

        this._searchResults = [];

        this._dummyHistoryItem = new DummyHistoryItem.GPasteDummyHistoryItem();

        this._searchItem = new SearchItem.GPasteSearchItem();
        this._searchItem.connect('text-changed', Lang.bind(this, this._onNewSearch));

        this._settingsSizeChangedId = this._settings.connect('changed::element-size', Lang.bind(this, this._resetElementSize));
        this._resetElementSize();
        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
        this.menu.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));

        this._pageSwitcher = new PageSwitcher.GPastePageSwitcher();
        this._pageSwitcher.connect('switch', Lang.bind(this, function(sw, page) {
            this._updatePage(page);
        }));

        this._actions = new PopupMenu.PopupBaseMenuItem({
            reactive: false,
            can_focus: false
        });

        this._addToPostHeader(this._dummyHistoryItem);
        this._addToPreFooter(new PopupMenu.PopupSeparatorMenuItem());
        this._addToFooter(this._actions);

        GPaste.Client.new(Lang.bind(this, function (obj, result) {
            this._client = GPaste.Client.new_finish(result);

            this._uiItem = new UiItem.GPasteUiItem(this.menu);
            this._emptyHistoryItem = new EmptyHistoryItem.GPasteEmptyHistoryItem(this._client);
            this._aboutItem = new AboutItem.GPasteAboutItem(this._client, this.menu);
            this._switch = new StateSwitch.GPasteStateSwitch(this._client);

            this._addToHeader(this._switch);
            this._addToHeader(this._searchItem);
            this._addToHeader(this._pageSwitcher);

            this._actions.actor.add(this._uiItem.actor, { expand: true, x_fill: false });
            this._actions.actor.add(this._emptyHistoryItem.actor, { expand: true, x_fill: false });
            this._actions.actor.add(this._aboutItem.actor, { expand: true, x_fill: false });

            this._settingsMaxSizeChangedId = this._settings.connect('changed::max-displayed-history-size', Lang.bind(this, this._resetMaxDisplayedSize));
            this._resetMaxDisplayedSize();

            this._clientUpdateId = this._client.connect('update', Lang.bind(this, this._update));
            this._clientShowId = this._client.connect('show-history', Lang.bind(this, this._popup));
            this._clientTrackingId = this._client.connect('tracking', Lang.bind(this, this._toggle));

            this._onStateChanged (true);

            this.menu.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
            this.menu.actor.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));

            this._destroyed = false;
            this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
        }));
    },

    shutdown: function() {
        this._onStateChanged (false);
        this._onDestroy();
        this.destroy();
    },

    _onKeyPressEvent: function(actor, event) {
        if (event.has_control_modifier()) {
            const nb = parseInt(event.get_key_unicode());
            if (!isNaN(nb) && nb >= 0 && nb <= 9 && nb < this._history.length) {
                this._history[nb].activate();
            }
        } else {
            this._maybeUpdateIndexVisibility(event, true);
        }
    },

    _onKeyReleaseEvent: function(actor, event) {
        this._maybeUpdateIndexVisibility(event, false);
    },

    _maybeUpdateIndexVisibility: function(event, state) {
        const key = event.get_key_symbol();
        if (key == Clutter.KEY_Control_L || key == Clutter.KEY_Control_R) {
            this._updateIndexVisibility(state);
        }
    },

    _updateIndexVisibility: function(state) {
        this._history.slice(0, 10).forEach(function(i) {
            i.showIndex(state);
        });
    },

    _hasSearch: function() {
        return this._searchItem.text.length > 0;
    },

    _onSearch: function(page) {
        if (this._hasSearch()) {
            const search = this._searchItem.text.toLowerCase();

            this._client.search(search, Lang.bind(this, function(client, result) {
                this._searchResults = client.search_finish(result);
                let results = this._searchResults.length;
                const maxSize = this._history.length;

                if (!this._pageSwitcher.updateForSize(results)) {
                    return;
                }

                this._pageSwitcher.setActive(page);
                const offset = this._pageSwitcher.getPageOffset();

                if (results > (maxSize + offset)) {
                    results = (maxSize + offset);
                }

                this._history.slice(0, results - offset).forEach(Lang.bind(this, function(i, index) {
                    i.setIndex(this._searchResults[offset + index]);
                }));

                /* If we had no result, updateForSize would have returned false */
                this._dummyHistoryItem.actor.hide();

                this._history.slice(results - offset, maxSize).forEach(function(i) {
                    i.setIndex(-1);
                });
            }));
        } else {
            this._searchResults = [];
            this._refresh(0);
        }
    },

    _onNewSearch: function() {
        this._onSearch(1);
    },

    _resetElementSize: function() {
        const size = this._settings.get_element_size();
        this._searchItem.resetSize(size/2 + 3);
        this._history.forEach(function(i) {
            i.setTextSize(size);
        });
    },

    _updatePage: function(page) {
        this._pageSwitcher.setActive(page);
        this._refresh(0);
    },

    _resetMaxDisplayedSize: function() {
        const oldSize = this._history.length;
        const newSize = this._settings.get_max_displayed_history_size();
        const elementSize = this._settings.get_element_size();

        this._pageSwitcher.setMaxDisplayedSize(newSize);

        const offset = this._pageSwitcher.getPageOffset();

        if (newSize > oldSize) {
            for (let index = oldSize; index < newSize; ++index) {
                let item = new Item.GPasteItem(this._client, elementSize, index + offset);
                this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize + index);
                this._history[index] = item;
            }
        } else {
            for (let i = newSize; i < oldSize; ++i) {
                this._history.pop().destroy();
            }
        }

        if (offset === 0 || oldSize === 0) {
            this._updatePage(1);
        } else {
            this._updatePage((offset / oldSize) + 1);
        }
    },

    _update: function(client, action, target, position) {
        switch (target) {
        case GPaste.UpdateTarget.ALL:
            this._refresh(0);
            break;
        case GPaste.UpdateTarget.POSITION:
            const offset = this._pageSwitcher.getPageOffset();
            const displayPos = position - offset;
            switch (action) {
            case GPaste.UpdateAction.REPLACE:
                this._history[displayPos].refresh();
                break;
            case GPaste.UpdateAction.REMOVE:
                this._refresh(displayPos);
                break;
            }
            break;
        }
    },

    _refresh: function(resetTextFrom) {
        if (this._searchResults.length > 0) {
            this._onSearch(this._pageSwitcher.getPage());
        } else if (this._hasSearch()) {
            this._history.forEach(function(i, index) {
                i.setIndex(-1);
            });
            this._updateVisibility(true);
        } else {
            this._client.get_history_name(Lang.bind(this, function(client, result) {
                const name = client.get_history_name_finish(result);

                this._client.get_history_size(name, Lang.bind(this, function(client, result) {
                    const realSize = client.get_history_size_finish(result);

                    if (!this._pageSwitcher.updateForSize(realSize)) {
                        return;
                    }

                    const maxSize = this._history.length;
                    const offset = this._pageSwitcher.getPageOffset();
                    const size = Math.min(realSize - offset, maxSize);

                    this._history.slice(resetTextFrom, size).forEach(function(i, index) {
                        i.setIndex(offset + index);
                    });
                    this._history.slice(size, maxSize).forEach(function(i, index) {
                        i.setIndex(-1);
                    });

                    this._updateVisibility(size == 0);
                }));
            }));
        }
    },

    _updateVisibility: function(empty, search) {
        if (!empty) {
            this._dummyHistoryItem.actor.hide();
            this._emptyHistoryItem.actor.show();
            this._searchItem.actor.show();
        } else if (this._hasSearch()) {
            this._dummyHistoryItem.showNoResult();
            this._emptyHistoryItem.actor.hide();
            this._searchItem.actor.show();
        } else {
            this._dummyHistoryItem.showEmpty();
            this._emptyHistoryItem.actor.hide();
            this._searchItem.actor.hide();
        }
    },

    _popup: function() {
        this.menu.open(true);
        this._selectSearch();
    },

    _toggle: function(c, state) {
        this._switch.toggle(state);
    },

    _selectSearch: function() {
        if (this._history.length > 0) {
            this._searchItem.grabFocus();
        }
    },

    _addToHeader: function(item) {
        this.menu.addMenuItem(item, this._headerSize++);
    },

    _addToPostHeader: function(item) {
        this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize++);
    },

    _addToPreFooter: function(item) {
        this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize + this._history.length + this._preFooterSize++);
    },

    _addToFooter: function(item) {
        this.menu.addMenuItem(item, this._headerSize + this._postHeaderSize + this._history.length + this._preFooterSize + this._footerSize++);
    },

    _onStateChanged: function(state) {
        this._client.on_extension_state_changed(state, null);
    },

    _onOpenStateChanged: function(menu, state) {
        if (state) {
            this._searchItem.reset();
            this._updatePage(1);
        } else {
            this._updateIndexVisibility(false);
        }
    },

    _onMenuKeyPress: function(actor, event) {
        const symbol = event.get_key_symbol();
        if (symbol == Clutter.KEY_Left) {
            return this._pageSwitcher.previous();
        }
        if (symbol == Clutter.KEY_Right) {
            return this._pageSwitcher.next();
        }
        return Clutter.EVENT_PROPAGATE;
    },

    _onDestroy: function() {
        if (this._destroyed) {
            return;
        }
        this._destroyed = true;
        this._client.disconnect(this._clientUpdateId);
        this._client.disconnect(this._clientShowId);
        this._client.disconnect(this._clientTrackingId);
        this._settings.disconnect(this._settingsMaxSizeChangedId);
        this._settings.disconnect(this._settingsSizeChangedId);
    }
});

<|endoftext|>


<commit_before>/*** Imports ***/
import GeometriesSlice from '../../src/geometries/geometries.slice';
import ShadersUniform  from '../../src/shaders/shaders.data.uniform';
import ShadersVertex   from '../../src/shaders/shaders.data.vertex';
import ShadersFragment from '../../src/shaders/shaders.data.fragment';

import HelpersMaterialMixin from '../../src/helpers/helpers.material.mixin';

/**
 * @module helpers/slice
 */

export default class HelpersSlice extends HelpersMaterialMixin( THREE.Object3D ){
  constructor(stack,
              index = 0,
              position = new THREE.Vector3(0, 0, 0),
              direction = new THREE.Vector3(0, 0, 1),
              aabbSpace = 'IJK') {
    //
    super();

    // private vars
    this._stack = stack;

    // image settings
    // index only used to grab window/level and intercept/slope
    this._invert = this._stack.invert;

    this._lut = 'none';
    this._lutTexture = null;
    // if auto === true, get from index
    // else from stack which holds the default values
    this._intensityAuto = true;
    this._interpolation = 1; // default to trilinear interpolation
    // starts at 0
    this._index = index;
    this._windowWidth = null;
    this._windowCenter = null;
    this._rescaleSlope = null;
    this._rescaleIntercept = null;

    // Object3D settings
    // shape
    this._planePosition = position;
    this._planeDirection = direction;
    // change aaBBSpace changes the box dimensions
    // also changes the transform
    // there is also a switch to move back mesh to LPS space automatically
    this._aaBBspace = aabbSpace; // or LPS -> different transforms, esp for the geometry/mesh
    this._material = null;
    this._textures = [];
    this._shadersFragment = ShadersFragment;
    this._shadersVertex = ShadersVertex;
    this._uniforms = ShadersUniform.uniforms();
    this._geometry = null;
    this._mesh = null;
    this._visible = true;

    // update dimensions, center, etc.
    // depending on aaBBSpace
    this._init();

    // update object
    this._create();
  }

  // getters/setters

  get stack() {
    return this._stack;
  }

  set stack(stack) {
    this._stack = stack;
  }

  get windowWidth() {
    return this._windowWidth;
  }

  set windowWidth(windowWidth) {
    this._windowWidth = windowWidth;
    this.updateIntensitySettingsUniforms();
  }

  get windowCenter() {
    return this._windowCenter;
  }

  set windowCenter(windowCenter) {
    this._windowCenter = windowCenter;
    this.updateIntensitySettingsUniforms();
  }

  get rescaleSlope() {
    return this._rescaleSlope;
  }

  set rescaleSlope(rescaleSlope) {
    this._rescaleSlope = rescaleSlope;
    this.updateIntensitySettingsUniforms();
  }

  get rescaleIntercept() {
    return this._rescaleIntercept;
  }

  set rescaleIntercept(rescaleIntercept) {
    this._rescaleIntercept = rescaleIntercept;
    this.updateIntensitySettingsUniforms();
  }

  get invert() {
    return this._invert;
  }

  set invert(invert) {
    this._invert = invert;
    this.updateIntensitySettingsUniforms();
  }

  get lut() {
    return this._lut;
  }

  set lut(lut) {
    this._lut = lut;
  }

  get lutTexture() {
    return this._lutTexture;
  }

  set lutTexture(lutTexture) {
    this._lutTexture = lutTexture;
    this.updateIntensitySettingsUniforms();
  }

  get intensityAuto() {
    return this._intensityAuto;
  }

  set intensityAuto(intensityAuto) {
    this._intensityAuto = intensityAuto;
    this.updateIntensitySettings();
    this.updateIntensitySettingsUniforms();
  }

  get interpolation() {
    return this._interpolation;
  }

  set interpolation(interpolation) {
    this._interpolation = interpolation;
    this.updateIntensitySettingsUniforms();
    this._updateMaterial();
  }

  get index() {
    return this._index;
  }

  set index(index) {
    this._index = index;
    this._update();
  }

  set planePosition(position) {
    this._planePosition = position;
    this._update();
  }

  get planePosition() {
    return this._planePosition;
  }

  set planeDirection(direction) {
    this._planeDirection = direction;
    this._update();
  }

  get planeDirection() {
    return this._planeDirection;
  }

  set halfDimensions(halfDimensions) {
    this._halfDimensions = halfDimensions;
  }

  get halfDimensions() {
    return this._halfDimensions;
  }

  set center(center) {
    this._center = center;
  }

  get center() {
    return this._center;
  }

  set aabbSpace(aabbSpace) {
    this._aaBBspace = aabbSpace;
    this._init();
  }

  get aabbSpace() {
    return this._aaBBspace;
  }

  set mesh(mesh) {
    this._mesh = mesh;
  }

  get mesh() {
    return this._mesh;
  }

  set geometry(geometry) {
    this._geometry = geometry;
  }

  get geometry() {
    return this._geometry;
  }

  _init() {
    if (!this._stack || !this._stack._prepared || !this._stack._packed) {
      return;
    }

    if (this._aaBBspace === 'IJK') {
      this._halfDimensions = this._stack.halfDimensionsIJK;
      this._center = new THREE.Vector3(
        this._stack.halfDimensionsIJK.x - 0.5,
        this._stack.halfDimensionsIJK.y - 0.5,
        this._stack.halfDimensionsIJK.z - 0.5);
      this._toAABB = new THREE.Matrix4();
    } else {
      // LPS
      let aaBBox  = this._stack.AABBox();
      this._halfDimensions = aaBBox.clone().multiplyScalar(0.5);
      this._center = this._stack.centerAABBox();
      this._toAABB = this._stack.lps2AABB;
    }
  }

  // private methods
  _create() {

    if (!this._stack || !this._stack.prepared || !this._stack.packed) {
      return;
    }

    // Convenience vars
    try {
      this._geometry = new GeometriesSlice(
        this._halfDimensions,
        this._center,
        this._planePosition,
        this._planeDirection,
        this._toAABB);
    }
    catch (e) {
      window.console.log(e);
      window.console.log('invalid slice geometry - exiting...');
      return;
    }

    if (!this._geometry.vertices) {
      return;
    }

    if (!this._material) {
      //
      this._uniforms.uTextureSize.value     = this._stack.textureSize;
      this._uniforms.uDataDimensions.value  = [ this._stack.dimensionsIJK.x,
                                                this._stack.dimensionsIJK.y,
                                                this._stack.dimensionsIJK.z ];
      this._uniforms.uWorldToData.value      = this._stack.lps2IJK;
      this._uniforms.uNumberOfChannels.value = this._stack.numberOfChannels;
      this._uniforms.uPixelType.value        = this._stack.pixelType;
      this._uniforms.uBitsAllocated.value    = this._stack.bitsAllocated;
      this._uniforms.uPackedPerPixel.value   = this._stack.packedPerPixel;
      // compute texture if material exist
      this._prepareTexture();
      this._uniforms.uTextureContainer.value = this._textures;

      this._createMaterial({
        side: THREE.DoubleSide
      });

    }

    // update intensity related stuff
    this.updateIntensitySettings();
    this.updateIntensitySettingsUniforms();

    // create the mesh!
    this._mesh = new THREE.Mesh(this._geometry, this._material);
    if (this._aaBBspace === 'IJK') {
      this._mesh.applyMatrix(this._stack.ijk2LPS);
    }

    this._mesh.visible = this._visible;

    // and add it!
    this.add(this._mesh);
  }

  updateIntensitySettings() {
    // if auto, get from frame index
    if (this._intensityAuto) {
      this.updateIntensitySetting('windowCenter');
      this.updateIntensitySetting('windowWidth');
      this.updateIntensitySetting('rescaleSlope');
      this.updateIntensitySetting('rescaleIntercept');
    } else {
      if (this._windowCenter === null) {
        this._windowCenter = this._stack.windowCenter;
      }

      if (this.__windowWidth === null) {
        this._windowWidth = this._stack.windowWidth;
      }

      if (this._rescaleSlope === null) {
        this._rescaleSlope = this._stack.rescaleSlope;
      }

      if (this._rescaleIntercept === null) {
        this._rescaleIntercept = this._stack.rescaleIntercept;
      }
    }

  }

  updateIntensitySettingsUniforms() {
    // set slice window center and width
    this._uniforms.uRescaleSlopeIntercept.value = [this._rescaleSlope, this._rescaleIntercept];
    this._uniforms.uWindowCenterWidth.value = [this._windowCenter, this._windowWidth];

    // invert
    this._uniforms.uInvert.value = this._invert === true ? 1 : 0;

    // interpolation
    this._uniforms.uInterpolation.value = this._interpolation;

    // lut
    if (this._lut === 'none') {
      this._uniforms.uLut.value = 0;
    } else {
      this._uniforms.uLut.value = 1;
      this._uniforms.uTextureLUT.value = this._lutTexture;
    }
  }

  updateIntensitySetting(setting) {
    if (this._stack.frame[this._index] &&
        this._stack.frame[this._index][setting]) {
      this['_' + setting] = this._stack.frame[this._index][setting];
    } else {
      this['_' + setting] = this._stack[setting];
    }
  }

  _update() {
    // update slice
    if (this._mesh) {
      this.remove(this._mesh);
      this._mesh.geometry.dispose();
      this._mesh.geometry = null;
      // we do not want to dispose the texture!
      // this._mesh.material.dispose();
      // this._mesh.material = null;
      this._mesh = null;
    }

    this._create();
  }
}
<commit_msg>update slice helper for negative intensities<commit_after>/*** Imports ***/
import GeometriesSlice from '../../src/geometries/geometries.slice';
import ShadersUniform  from '../../src/shaders/shaders.data.uniform';
import ShadersVertex   from '../../src/shaders/shaders.data.vertex';
import ShadersFragment from '../../src/shaders/shaders.data.fragment';

import HelpersMaterialMixin from '../../src/helpers/helpers.material.mixin';

/**
 * @module helpers/slice
 */

export default class HelpersSlice extends HelpersMaterialMixin( THREE.Object3D ){
  constructor(stack,
              index = 0,
              position = new THREE.Vector3(0, 0, 0),
              direction = new THREE.Vector3(0, 0, 1),
              aabbSpace = 'IJK') {
    //
    super();

    // private vars
    this._stack = stack;

    // image settings
    // index only used to grab window/level and intercept/slope
    this._invert = this._stack.invert;

    this._lut = 'none';
    this._lutTexture = null;
    // if auto === true, get from index
    // else from stack which holds the default values
    this._intensityAuto = true;
    this._interpolation = 1; // default to trilinear interpolation
    // starts at 0
    this._index = index;
    this._windowWidth = null;
    this._windowCenter = null;
    this._rescaleSlope = null;
    this._rescaleIntercept = null;

    // Object3D settings
    // shape
    this._planePosition = position;
    this._planeDirection = direction;
    // change aaBBSpace changes the box dimensions
    // also changes the transform
    // there is also a switch to move back mesh to LPS space automatically
    this._aaBBspace = aabbSpace; // or LPS -> different transforms, esp for the geometry/mesh
    this._material = null;
    this._textures = [];
    this._shadersFragment = ShadersFragment;
    this._shadersVertex = ShadersVertex;
    this._uniforms = ShadersUniform.uniforms();
    this._geometry = null;
    this._mesh = null;
    this._visible = true;

    // update dimensions, center, etc.
    // depending on aaBBSpace
    this._init();

    // update object
    this._create();
  }

  // getters/setters

  get stack() {
    return this._stack;
  }

  set stack(stack) {
    this._stack = stack;
  }

  get windowWidth() {
    return this._windowWidth;
  }

  set windowWidth(windowWidth) {
    this._windowWidth = windowWidth;
    this.updateIntensitySettingsUniforms();
  }

  get windowCenter() {
    return this._windowCenter;
  }

  set windowCenter(windowCenter) {
    this._windowCenter = windowCenter;
    this.updateIntensitySettingsUniforms();
  }

  get rescaleSlope() {
    return this._rescaleSlope;
  }

  set rescaleSlope(rescaleSlope) {
    this._rescaleSlope = rescaleSlope;
    this.updateIntensitySettingsUniforms();
  }

  get rescaleIntercept() {
    return this._rescaleIntercept;
  }

  set rescaleIntercept(rescaleIntercept) {
    this._rescaleIntercept = rescaleIntercept;
    this.updateIntensitySettingsUniforms();
  }

  get invert() {
    return this._invert;
  }

  set invert(invert) {
    this._invert = invert;
    this.updateIntensitySettingsUniforms();
  }

  get lut() {
    return this._lut;
  }

  set lut(lut) {
    this._lut = lut;
  }

  get lutTexture() {
    return this._lutTexture;
  }

  set lutTexture(lutTexture) {
    this._lutTexture = lutTexture;
    this.updateIntensitySettingsUniforms();
  }

  get intensityAuto() {
    return this._intensityAuto;
  }

  set intensityAuto(intensityAuto) {
    this._intensityAuto = intensityAuto;
    this.updateIntensitySettings();
    this.updateIntensitySettingsUniforms();
  }

  get interpolation() {
    return this._interpolation;
  }

  set interpolation(interpolation) {
    this._interpolation = interpolation;
    this.updateIntensitySettingsUniforms();
    this._updateMaterial();
  }

  get index() {
    return this._index;
  }

  set index(index) {
    this._index = index;
    this._update();
  }

  set planePosition(position) {
    this._planePosition = position;
    this._update();
  }

  get planePosition() {
    return this._planePosition;
  }

  set planeDirection(direction) {
    this._planeDirection = direction;
    this._update();
  }

  get planeDirection() {
    return this._planeDirection;
  }

  set halfDimensions(halfDimensions) {
    this._halfDimensions = halfDimensions;
  }

  get halfDimensions() {
    return this._halfDimensions;
  }

  set center(center) {
    this._center = center;
  }

  get center() {
    return this._center;
  }

  set aabbSpace(aabbSpace) {
    this._aaBBspace = aabbSpace;
    this._init();
  }

  get aabbSpace() {
    return this._aaBBspace;
  }

  set mesh(mesh) {
    this._mesh = mesh;
  }

  get mesh() {
    return this._mesh;
  }

  set geometry(geometry) {
    this._geometry = geometry;
  }

  get geometry() {
    return this._geometry;
  }

  _init() {
    if (!this._stack || !this._stack._prepared || !this._stack._packed) {
      return;
    }

    if (this._aaBBspace === 'IJK') {
      this._halfDimensions = this._stack.halfDimensionsIJK;
      this._center = new THREE.Vector3(
        this._stack.halfDimensionsIJK.x - 0.5,
        this._stack.halfDimensionsIJK.y - 0.5,
        this._stack.halfDimensionsIJK.z - 0.5);
      this._toAABB = new THREE.Matrix4();
    } else {
      // LPS
      let aaBBox  = this._stack.AABBox();
      this._halfDimensions = aaBBox.clone().multiplyScalar(0.5);
      this._center = this._stack.centerAABBox();
      this._toAABB = this._stack.lps2AABB;
    }
  }

  // private methods
  _create() {

    if (!this._stack || !this._stack.prepared || !this._stack.packed) {
      return;
    }

    // Convenience vars
    try {
      this._geometry = new GeometriesSlice(
        this._halfDimensions,
        this._center,
        this._planePosition,
        this._planeDirection,
        this._toAABB);
    }
    catch (e) {
      window.console.log(e);
      window.console.log('invalid slice geometry - exiting...');
      return;
    }

    if (!this._geometry.vertices) {
      return;
    }

    if (!this._material) {
      //
      this._uniforms.uTextureSize.value     = this._stack.textureSize;
      this._uniforms.uDataDimensions.value  = [ this._stack.dimensionsIJK.x,
                                                this._stack.dimensionsIJK.y,
                                                this._stack.dimensionsIJK.z ];
      this._uniforms.uWorldToData.value      = this._stack.lps2IJK;
      this._uniforms.uNumberOfChannels.value = this._stack.numberOfChannels;
      this._uniforms.uPixelType.value        = this._stack.pixelType;
      this._uniforms.uBitsAllocated.value    = this._stack.bitsAllocated;
      this._uniforms.uPackedPerPixel.value   = this._stack.packedPerPixel;
      // compute texture if material exist
      this._prepareTexture();
      this._uniforms.uTextureContainer.value = this._textures;

      this._createMaterial({
        side: THREE.DoubleSide
      });

    }

    // update intensity related stuff
    this.updateIntensitySettings();
    this.updateIntensitySettingsUniforms();

    // create the mesh!
    this._mesh = new THREE.Mesh(this._geometry, this._material);
    if (this._aaBBspace === 'IJK') {
      this._mesh.applyMatrix(this._stack.ijk2LPS);
    }

    this._mesh.visible = this._visible;

    // and add it!
    this.add(this._mesh);
  }

  updateIntensitySettings() {
    // if auto, get from frame index
    if (this._intensityAuto) {
      this.updateIntensitySetting('windowCenter');
      this.updateIntensitySetting('windowWidth');
      this.updateIntensitySetting('rescaleSlope');
      this.updateIntensitySetting('rescaleIntercept');
    } else {
      if (this._windowCenter === null) {
        this._windowCenter = this._stack.windowCenter;
      }

      if (this.__windowWidth === null) {
        this._windowWidth = this._stack.windowWidth;
      }

      if (this._rescaleSlope === null) {
        this._rescaleSlope = this._stack.rescaleSlope;
      }

      if (this._rescaleIntercept === null) {
        this._rescaleIntercept = this._stack.rescaleIntercept;
      }
    }

  }

  updateIntensitySettingsUniforms() {

    let offset = 0;
    if( this._stack._minMax[0] < 0 ){

      offset -= this._stack._minMax[0];

    }

    // set slice window center and width
    this._uniforms.uRescaleSlopeIntercept.value = [this._rescaleSlope, this._rescaleIntercept];
    this._uniforms.uWindowCenterWidth.value = [ offset + this._windowCenter, this._windowWidth];

    // invert
    this._uniforms.uInvert.value = this._invert === true ? 1 : 0;

    // interpolation
    this._uniforms.uInterpolation.value = this._interpolation;

    // lut
    if (this._lut === 'none') {
      this._uniforms.uLut.value = 0;
    } else {
      this._uniforms.uLut.value = 1;
      this._uniforms.uTextureLUT.value = this._lutTexture;
    }
  }

  updateIntensitySetting(setting) {
    if (this._stack.frame[this._index] &&
        this._stack.frame[this._index][setting]) {
      this['_' + setting] = this._stack.frame[this._index][setting];
    } else {
      this['_' + setting] = this._stack[setting];
    }
  }

  _update() {
    // update slice
    if (this._mesh) {
      this.remove(this._mesh);
      this._mesh.geometry.dispose();
      this._mesh.geometry = null;
      // we do not want to dispose the texture!
      // this._mesh.material.dispose();
      // this._mesh.material = null;
      this._mesh = null;
    }

    this._create();
  }
}
<|endoftext|>