<commit_before>lobby.transporter.module.create('outliners', function(thisModule) {


thisModule.addSlots(modules.outliners, function(add) {
    
    add.data('_directory', 'outliners');

});


thisModule.addSlots(lobby, function(add) {

  add.method('OutlinerMorph', function OutlinerMorph() { Class.initializer.apply(this, arguments); }, {category: ['outliners']});

  add.data('livelyOutliners', {}, {category: ['outliners']});
});


thisModule.addSlots(OutlinerMorph, function(add) {

  add.data('superclass', ColumnMorph);

  add.creator('prototype', Object.create(ColumnMorph.prototype), {}, {copyDownParents: [{parent: CategoryMorphMixin}]});

  add.data('type', 'OutlinerMorph');

});


thisModule.addSlots(OutlinerMorph.prototype, function(add) {

  add.data('constructor', OutlinerMorph);

  add.method('initialize', function ($super, m) {
    $super();
    this._mirror = m;

    this.setPadding({top: 2, bottom: 2, left: 4, right: 4, between: 2});
    this.shape.roundEdgesBy(10);

    this._slotMorphs     = dictionary.copyRemoveAll();
    this._categoryMorphs = dictionary.copyRemoveAll();

    this.initializeCategoryUI(); // aaa - can be a bit slow
    
    this._evaluatorsPanel = new ColumnMorph().beInvisible();
    this._evaluatorsPanel.horizontalLayoutMode = LayoutModes.SpaceFill;

    this.titleLabel = createLabel(function() {return m.inspect();});
    // this.titleLabel.setFontFamily('serif'); // not sure I like it
    // this.titleLabel.setEmphasis({style: 'bold'}); // I like it, except that the layout gets messed up

    this._commentToggler    = Object.newChildOf(toggler, this.updateExpandedness.bind(this), this.mirror().canHaveAnnotation() ? this.createRow(this.   commentMorph()) : null);
    this._annotationToggler = Object.newChildOf(toggler, this.updateExpandedness.bind(this), this.mirror().canHaveAnnotation() ?                this.annotationMorph()  : null);

    this.commentButton   = createButton("'...'", function(evt) { this._commentToggler.toggle(evt); }.bind(this), 1);
    this.evaluatorButton = createButton("E", function(evt) { this.openEvaluator(evt); }.bind(this), 1);
    this.dismissButton   = this.createDismissButton();

    this.optionalCommentButtonMorph = createOptionalMorph(this.commentButton, function() { return this._commentToggler.isOn() || (this.mirror().comment && this.mirror().comment()); }.bind(this));

    this._headerRow = createSpaceFillingRow([this._expander, this.titleLabel, this.optionalCommentButtonMorph, createSpacer(), this.evaluatorButton, this.dismissButton],
                                            {top: 0, bottom: 0, left: 0, right: 0, between: 3});
    this._headerRow.refreshContent();

    this.optionalSlotsPanel = createOptionalMorph(function() {return this.slotsPanel();}.bind(this),
                                                  function() {return this.expander().isExpanded();}.bind(this),
                                                  {horizontalLayoutMode: LayoutModes.SpaceFill, verticalLayoutMode: LayoutModes.ShrinkWrap});

    this.setPotentialContent([this._headerRow, this._annotationToggler, this._commentToggler, this.optionalSlotsPanel, this._evaluatorsPanel]);

    this.refreshContent();

    this.startPeriodicallyUpdating();
  }, {category: ['creating']});

  add.method('mirror', function () { return this._mirror; }, {category: ['accessing']});

  add.method('outliner', function () { return this; }, {comment: 'For compatibility for CategoryMorph.', category: ['accessing']});

  add.method('category', function () { return Category.root(); }, {category: ['accessing']});

  add.method('createRow', function (m) {
    var r = createSpaceFillingRow([m], {left: 15, right: 2, top: 2, bottom: 2, between: 0});
    r.wasJustShown = function(evt) { m.requestKeyboardFocus(evt.hand); };
    return r;
  }, {category: ['creating']});

  add.method('annotationMorph', function () {
    var m = this._annotationMorph;
    if (m) { return m; }
    m = this._annotationMorph = new ColumnMorph(this).beInvisible();
    m.horizontalLayoutMode = LayoutModes.SpaceFill;

    // aaa - shouldn't really be a string; do something nicer, some way of specifying a list
    this._copyDownParentsLabel = createInputBox(this.copyDownParentsString.bind(this), this.setCopyDownParentsString.bind(this));
    m.setRows([createLabelledNode("Copy-down parents", this._copyDownParentsLabel)]);
    return m;
  }, {category: ['annotation']});

  add.method('copyDownParentsString', function () {
    return reflect(this.mirror().copyDownParents()).expressionEvaluatingToMe();
  }, {category: ['annotation']});

  add.method('setCopyDownParentsString', function (str) {
    MessageNotifierMorph.showIfErrorDuring(function() {
      this.mirror().setCopyDownParents(eval(str));
    }.bind(this), createFakeEvent());
    this.updateAppearance(); // to make the copied-down slots appear
  }, {category: ['annotation']});

  add.method('updateAppearance', function () {
    if (! this.world()) {return;}
    this.populateSlotsPanelInMeAndExistingSubcategoryMorphs();
    this.refreshContentOfMeAndSubmorphs();
  }, {category: ['updating']});

  add.method('startPeriodicallyUpdating', function () {
    this._updater = new PeriodicalExecuter(function(pe) { this.updateAppearance(); }.bind(this), 8);
  }, {category: ['updating']});

  add.method('inspect', function () {return this.mirror().inspect();}, {category: ['printing']});

  add.method('updateExpandedness', function () {
    if (! this.world()) {return;}
    this.optionalSlotsPanel.refreshContent();
    this.refreshContent();
  }, {category: ['updating']});

  add.method('expandCategory', function (c) {
    var m = c.isRoot() ? this : this.categoryMorphFor(c);
    m.expander().expand();
    m.populateSlotsPanel();
  }, {category: ['categories']});

  add.method('eachSlot', function (f) {
    this.mirror().eachFakeSlot(f);
    this.mirror().eachSlotInCategory(this.category(), f);
  }, {category: ['iterating']});

  add.method('slotMorphFor', function (s) {
    return this._slotMorphs.getOrIfAbsentPut(s.name(), function() { return new SlotMorph(s); });
  }, {category: ['slots panel']});

  add.method('existingCategoryMorphFor', function (c) {
    return this._categoryMorphs.get(c.fullName());
  }, {category: ['categories']});

  add.method('categoryMorphFor', function (c) {
    return this._categoryMorphs.getOrIfAbsentPut(c.fullName(), function() { return new CategoryMorph(this, c); }.bind(this));
  }, {category: ['categories']});

  add.method('commentMorph', function () {
    var m = this._commentMorph;
    if (m) { return m; }
    var thisOutliner = this;
    m = createInputBox(function( ) { return thisOutliner.mirror().comment(); },
                       function(c) { thisOutliner.mirror().setComment(c); });
    this._commentMorph = m;
    return m;
  }, {category: ['comment']});

  add.method('openEvaluator', function (evt) {
    var e = new EvaluatorMorph(this);
    this._evaluatorsPanel.addRow(e);
    e.wasJustShown(evt);
  }, {category: ['evaluators']});

  add.method('addCommandsTo', function (cmdList) {
    this.addCategoryCommandsTo(cmdList);

    cmdList.addLine();
    if (this.mirror().canHaveChildren()) {
      cmdList.addItem({label: "create child", go: function(evt) { this.createChild(evt); }.bind(this)});
    }

    if (this.mirror().isReflecteeProbablyAClass()) {
      cmdList.addItem({label: "create subclass", go: function(evt) { this.createSubclass(evt); }.bind(this)});
    }

    if (this.mirror().hasAccessibleParent()) {
      cmdList.addItem({label: "get my parent", go: function(evt) { evt.hand.world().morphFor(this.mirror().parent()).grabMe(evt); }.bind(this)});
    }
    
    if (this.mirror().canHaveAnnotation()) {
      cmdList.addLine();

      if (this.mirror().comment) {
        cmdList.addItem({label: this._commentToggler.isOn() ? "hide comment" : "show comment", go: function(evt) { this._commentToggler.toggle(evt); }.bind(this)});
      }

      cmdList.addItem({label: this._annotationToggler.isOn() ? "hide annotation" : "show annotation", go: function(evt) { this._annotationToggler.toggle(evt); }.bind(this)});

      cmdList.addItem({label: "set module...", go: function(evt) {
        var all = {};
        var chooseTargetModule = function(sourceModuleName, evt) {
          transporter.chooseOrCreateAModule(evt, this, "To which module?", function(targetModule, evt) {
            this.mirror().eachNormalSlot(function(slot) {
              if (! slot.isFromACopyDownParent()) {
                if (sourceModuleName === all || (!slot.module() && sourceModuleName === '-') || (slot.module() && slot.module().name() === sourceModuleName)) {
                  slot.setModule(targetModule);<commit_msg>Added a "get my parent" button, like Self has.<commit_after>lobby.transporter.module.create('outliners', function(thisModule) {


thisModule.addSlots(modules.outliners, function(add) {
    
    add.data('_directory', 'outliners');

});


thisModule.addSlots(lobby, function(add) {

  add.method('OutlinerMorph', function OutlinerMorph() { Class.initializer.apply(this, arguments); }, {category: ['outliners']});

  add.data('livelyOutliners', {}, {category: ['outliners']});
});


thisModule.addSlots(OutlinerMorph, function(add) {

  add.data('superclass', ColumnMorph);

  add.creator('prototype', Object.create(ColumnMorph.prototype), {}, {copyDownParents: [{parent: CategoryMorphMixin}]});

  add.data('type', 'OutlinerMorph');

});


thisModule.addSlots(OutlinerMorph.prototype, function(add) {

  add.data('constructor', OutlinerMorph);

  add.method('initialize', function ($super, m) {
    $super();
    this._mirror = m;

    this.setPadding({top: 2, bottom: 2, left: 4, right: 4, between: 2});
    this.shape.roundEdgesBy(10);

    this._slotMorphs     = dictionary.copyRemoveAll();
    this._categoryMorphs = dictionary.copyRemoveAll();

    this.initializeCategoryUI(); // aaa - can be a bit slow
    
    this._evaluatorsPanel = new ColumnMorph().beInvisible();
    this._evaluatorsPanel.horizontalLayoutMode = LayoutModes.SpaceFill;

    this.titleLabel = createLabel(function() {return m.inspect();});
    // this.titleLabel.setFontFamily('serif'); // not sure I like it
    // this.titleLabel.setEmphasis({style: 'bold'}); // I like it, except that the layout gets messed up

    this._commentToggler    = Object.newChildOf(toggler, this.updateExpandedness.bind(this), this.mirror().canHaveAnnotation() ? this.createRow(this.   commentMorph()) : null);
    this._annotationToggler = Object.newChildOf(toggler, this.updateExpandedness.bind(this), this.mirror().canHaveAnnotation() ?                this.annotationMorph()  : null);

    this.commentButton   = createButton("'...'", function(evt) { this._commentToggler.toggle(evt); }.bind(this), 1);
    this.parentButton    = createButton("^",     function(evt) { this.getParent(evt); }.bind(this), 1);
    this.evaluatorButton = createButton("E",     function(evt) { this.openEvaluator(evt); }.bind(this), 1);
    this.dismissButton   = this.createDismissButton();

    var optionalParentButtonMorph  = createOptionalMorph(this.parentButton,  function() { return this.mirror().hasAccessibleParent(); }.bind(this));
    var optionalCommentButtonMorph = createOptionalMorph(this.commentButton, function() { return this._commentToggler.isOn() || (this.mirror().comment && this.mirror().comment()); }.bind(this));
    
    this._headerRow = createSpaceFillingRow([this._expander, this.titleLabel, optionalCommentButtonMorph, createSpacer(), optionalParentButtonMorph, this.evaluatorButton, this.dismissButton],
                                            {top: 0, bottom: 0, left: 0, right: 0, between: 3});
    this._headerRow.refreshContentOfMeAndSubmorphs();

    this.optionalSlotsPanel = createOptionalMorph(function() {return this.slotsPanel();}.bind(this),
                                                  function() {return this.expander().isExpanded();}.bind(this),
                                                  {horizontalLayoutMode: LayoutModes.SpaceFill, verticalLayoutMode: LayoutModes.ShrinkWrap});

    this.setPotentialContent([this._headerRow, this._annotationToggler, this._commentToggler, this.optionalSlotsPanel, this._evaluatorsPanel]);

    this.refreshContent();

    this.startPeriodicallyUpdating();
  }, {category: ['creating']});

  add.method('mirror', function () { return this._mirror; }, {category: ['accessing']});

  add.method('outliner', function () { return this; }, {comment: 'For compatibility for CategoryMorph.', category: ['accessing']});

  add.method('category', function () { return Category.root(); }, {category: ['accessing']});

  add.method('createRow', function (m) {
    var r = createSpaceFillingRow([m], {left: 15, right: 2, top: 2, bottom: 2, between: 0});
    r.wasJustShown = function(evt) { m.requestKeyboardFocus(evt.hand); };
    return r;
  }, {category: ['creating']});

  add.method('annotationMorph', function () {
    var m = this._annotationMorph;
    if (m) { return m; }
    m = this._annotationMorph = new ColumnMorph(this).beInvisible();
    m.horizontalLayoutMode = LayoutModes.SpaceFill;

    // aaa - shouldn't really be a string; do something nicer, some way of specifying a list
    this._copyDownParentsLabel = createInputBox(this.copyDownParentsString.bind(this), this.setCopyDownParentsString.bind(this));
    m.setRows([createLabelledNode("Copy-down parents", this._copyDownParentsLabel)]);
    return m;
  }, {category: ['annotation']});

  add.method('copyDownParentsString', function () {
    return reflect(this.mirror().copyDownParents()).expressionEvaluatingToMe();
  }, {category: ['annotation']});

  add.method('setCopyDownParentsString', function (str) {
    MessageNotifierMorph.showIfErrorDuring(function() {
      this.mirror().setCopyDownParents(eval(str));
    }.bind(this), createFakeEvent());
    this.updateAppearance(); // to make the copied-down slots appear
  }, {category: ['annotation']});

  add.method('updateAppearance', function () {
    if (! this.world()) {return;}
    this.populateSlotsPanelInMeAndExistingSubcategoryMorphs();
    this.refreshContentOfMeAndSubmorphs();
  }, {category: ['updating']});

  add.method('startPeriodicallyUpdating', function () {
    this._updater = new PeriodicalExecuter(function(pe) { this.updateAppearance(); }.bind(this), 8);
  }, {category: ['updating']});

  add.method('inspect', function () {return this.mirror().inspect();}, {category: ['printing']});

  add.method('updateExpandedness', function () {
    if (! this.world()) {return;}
    this.optionalSlotsPanel.refreshContent();
    this.refreshContent();
  }, {category: ['updating']});

  add.method('expandCategory', function (c) {
    var m = c.isRoot() ? this : this.categoryMorphFor(c);
    m.expander().expand();
    m.populateSlotsPanel();
  }, {category: ['categories']});

  add.method('eachSlot', function (f) {
    this.mirror().eachFakeSlot(f);
    this.mirror().eachSlotInCategory(this.category(), f);
  }, {category: ['iterating']});

  add.method('slotMorphFor', function (s) {
    return this._slotMorphs.getOrIfAbsentPut(s.name(), function() { return new SlotMorph(s); });
  }, {category: ['slots panel']});

  add.method('existingCategoryMorphFor', function (c) {
    return this._categoryMorphs.get(c.fullName());
  }, {category: ['categories']});

  add.method('categoryMorphFor', function (c) {
    return this._categoryMorphs.getOrIfAbsentPut(c.fullName(), function() { return new CategoryMorph(this, c); }.bind(this));
  }, {category: ['categories']});

  add.method('commentMorph', function () {
    var m = this._commentMorph;
    if (m) { return m; }
    var thisOutliner = this;
    m = createInputBox(function( ) { return thisOutliner.mirror().comment(); },
                       function(c) { thisOutliner.mirror().setComment(c); });
    this._commentMorph = m;
    return m;
  }, {category: ['comment']});

  add.method('openEvaluator', function (evt) {
    var e = new EvaluatorMorph(this);
    this._evaluatorsPanel.addRow(e);
    e.wasJustShown(evt);
  }, {category: ['evaluators']});

  add.method('getParent', function (evt) {
    evt.hand.world().morphFor(this.mirror().parent()).grabMe(evt);
  }, {category: ['menu']});

  add.method('addCommandsTo', function (cmdList) {
    this.addCategoryCommandsTo(cmdList);

    cmdList.addLine();
    if (this.mirror().canHaveChildren()) {
      cmdList.addItem({label: "create child", go: function(evt) { this.createChild(evt); }.bind(this)});
    }

    if (this.mirror().isReflecteeProbablyAClass()) {
      cmdList.addItem({label: "create subclass", go: function(evt) { this.createSubclass(evt); }.bind(this)});
    }

    if (this.mirror().hasAccessibleParent()) {
      cmdList.addItem({label: "get my parent", go: function(evt) { this.getParent(evt); }.bind(this)});
    }
    
    if (this.mirror().canHaveAnnotation()) {
      cmdList.addLine();

      if (this.mirror().comment) {
        cmdList.addItem({label: this._commentToggler.isOn() ? "hide comment" : "show comment", go: function(evt) { this._commentToggler.toggle(evt); }.bind(this)});
      }

      cmdList.addItem({label: this._annotationToggler.isOn() ? "hide annotation" : "show annotation", go: function(evt) { this._annotationToggler.toggle(evt); }.bind(this)});

      cmdList.addItem({label: "set module...", go: function(evt) {
        var all = {};
        var chooseTargetModule = function(sourceModuleName, evt) {
          transporter.chooseOrCreateAModule(evt, this, "To which module?", function(targetModule, evt) {
            this.mirror().eachNormalSlot(function(slot) {
              if (! slot.isFromACopyDownParent()) {
                if (sourceModuleName === all || (!slot.module() && sourceModuleName === '-') || (slot.module() && slot.module().name() === sourceModuleName)) {
                  slot.setModule(targetModule);
{'fraction_non_alphanumeric': 0.16886381409898335, 'fraction_numerical': 0.0024019662607529884, 'mean_word_length': 4.192285382830627, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3387952', 'n_tokens_mistral': 5626, 'n_tokens_neox': 5498, 'n_words': 986}