The Trunk: Monticello-eem.617.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Monticello-eem.617.mcz

commits-2
Eliot Miranda uploaded a new version of Monticello to project The Trunk:
http://source.squeak.org/trunk/Monticello-eem.617.mcz

==================== Summary ====================

Name: Monticello-eem.617
Author: eem
Time: 27 August 2015, 5:09:02.395 pm
UUID: 4330481f-87ae-4d7b-b2aa-0969f0611256
Ancestors: Monticello-cmm.616

Add a menu item to nuke Monticello load change sets.  This is more involved than it should be but we're getting there.  Needs Morphic-eem.1002

=============== Diff against Monticello-cmm.616 ===============

Item was added:
+ ----- Method: ChangeSet>>isForPackageLoad (in category '*Monticello-testing') -----
+ isForPackageLoad
+ | packageName |
+ ^(name includes: $-)
+  and: [name last isDigit
+  and: [packageName := name first: ((name indexOf: $. ifAbsent: [name size])
+ min: (name lastIndexOf: $-)) - 1.
+ MCWorkingCopy allManagers anySatisfy: [:wc| wc packageName = packageName]]]!

Item was added:
+ ----- Method: ChangeSorter>>deleteMonticelloChangeSets (in category '*Monticello-changeSet menu') -----
+ deleteMonticelloChangeSets
+ "Destroy all change sets from Monticello loads, provided the currently selected change set is not one of those, and the user really wants to do this."
+
+ myChangeSet isForPackageLoad ifTrue: "forms current changes for current project"
+ [^self inform: 'current change set is a Monticello load change set.\Please select some other change set before deleting Monticello load change sets.' withCRs].
+ (self confirm: 'Are you sure you want to delete all change sets due to Monticello package loads?') ifFalse:
+ [^self].
+
+ (ChangesOrganizer allChangeSets select: [:cs| cs isForPackageLoad]) do:
+ [:cs| ChangesOrganizer removeChangeSet: cs].
+
+ self changed: #changeSetList.
+ self showChangeSet: ChangeSet current!

Item was added:
+ ----- Method: ChangeSorter>>monticelloChangeSetMenu: (in category '*Monticello-changeSet menu') -----
+ monticelloChangeSetMenu: aMenu
+ <changeSetMenuShifted: false>
+ <menuPriority: 600>
+ "Sigh, when implementing menu pragmas this is not what I had in mind..."
+ aMenu add: 'delete Monticello load change sets' action: #deleteMonticelloChangeSets.
+ (aMenu submorphs
+ detect: [:m| m isMenuItemMorph and: [m contents beginsWith: 'destroy change set']]
+ ifNone: []) ifNotNil:
+ [:destroyItem| | item |
+ aMenu removeMorph: (item := aMenu submorphs last).
+ aMenu addMorph: item after: destroyItem].
+ ^aMenu!


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Monticello-eem.617.mcz

Tobias Pape
Hi Eliot,

On 28.08.2015, at 00:09, [hidden email] wrote:

> Item was added:
> + ----- Method: ChangeSorter>>monticelloChangeSetMenu: (in category '*Monticello-changeSet menu') -----
> + monticelloChangeSetMenu: aMenu
> + <changeSetMenuShifted: false>
> + <menuPriority: 600>
> + "Sigh, when implementing menu pragmas this is not what I had in mind..."
> + aMenu add: 'delete Monticello load change sets' action: #deleteMonticelloChangeSets.
> + (aMenu submorphs
> + detect: [:m| m isMenuItemMorph and: [m contents beginsWith: 'destroy change set']]
> + ifNone: []) ifNotNil:
> + [:destroyItem| | item |
> + aMenu removeMorph: (item := aMenu submorphs last).
> + aMenu addMorph: item after: destroyItem].
> + ^aMenu!

Can you explain what you want to achieve
and how I can make this more convenient?

Best regards
        -Tobias


Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Monticello-eem.617.mcz

Kjell Godo
Pardon me for butting in but

I am interested in creating a new   Class of pop up menu   in Pharo

that doesn't look or act anything like the standard pop up Menus

and I would like to know where in the Pharo code I can

get between a 

right click   and its    pop up Menu opening

and open up my own MyMenu instead of the standard Menu

I'm guessing i should start with the Menu Class and maybe

make MyMenu be a subClass of Menu?

Should i ask questions like this on stack overflow instead?

It seems to me that the following   monticelloChangeSetMenu:   code is

Adding an new item mc to aMenu
finding a different menu item dc in aMenu
if dc exists
      remove the mc item from aMenu
      and add mc right after dc in aMenu

I don't know what a 

<menu pragma> is

can you point me at an explanation?

Does it allow a Method to be selected at runtime

according to its pragmas?



On Thursday, August 27, 2015, Tobias Pape <[hidden email]> wrote:
Hi Eliot,

On 28.08.2015, at 00:09, <a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;commits@source.squeak.org&#39;)">commits@... wrote:

> Item was added:
> + ----- Method: ChangeSorter>>monticelloChangeSetMenu: (in category '*Monticello-changeSet menu') -----
> + monticelloChangeSetMenu: aMenu
> +     <changeSetMenuShifted: false>
> +     <menuPriority: 600>
> +     "Sigh, when implementing menu pragmas this is not what I had in mind..."
> +     aMenu add: 'delete Monticello load change sets' action: #deleteMonticelloChangeSets.
> +     (aMenu submorphs
> +                                             detect: [:m| m isMenuItemMorph and: [m contents beginsWith: 'destroy change set']]
> +                                             ifNone: []) ifNotNil:
> +             [:destroyItem| | item |
> +             aMenu removeMorph: (item := aMenu submorphs last).
> +             aMenu addMorph: item after: destroyItem].
> +     ^aMenu!

Can you explain what you want to achieve
and how I can make this more convenient?

Best regards
        -Tobias




Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Monticello-eem.617.mcz

timrowledge

On 28-08-2015, at 1:35 AM, Kjell Godo <[hidden email]> wrote:

> Pardon me for butting in but
>
> I am interested in creating a new   Class of pop up menu   in Pharo
>
> that doesn't look or act anything like the standard pop up Menus

Kjell, you don’t neccessarily need to make a subclass of the current Menu, just so long as your class implements enough of the same methods that it works ok.  It’s kind of an obvious point but one I see people forgetting far too often. You may not want many - or any - of the same instance variables or internal behaviours.

All you should need to do is implement your menu (round menus![1] with sparkles!) and add a way to decide which menu class gets used.


tim
[1] round menus have actually been used, not least in the ancient Momenta Smalltalk based tablets of the late 80’s/very early 90’s.
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Why do we want intelligent terminals when there are so many stupid users?



Reply | Threaded
Open this post in threaded view
|

Re: The Trunk: Monticello-eem.617.mcz

Eliot Miranda-2
In reply to this post by Tobias Pape
Hi Tobias,

On Thu, Aug 27, 2015 at 10:56 PM, Tobias Pape <[hidden email]> wrote:
Hi Eliot,

On 28.08.2015, at 00:09, [hidden email] wrote:

> Item was added:
> + ----- Method: ChangeSorter>>monticelloChangeSetMenu: (in category '*Monticello-changeSet menu') -----
> + monticelloChangeSetMenu: aMenu
> +     <changeSetMenuShifted: false>
> +     <menuPriority: 600>
> +     "Sigh, when implementing menu pragmas this is not what I had in mind..."
> +     aMenu add: 'delete Monticello load change sets' action: #deleteMonticelloChangeSets.
> +     (aMenu submorphs
> +                                             detect: [:m| m isMenuItemMorph and: [m contents beginsWith: 'destroy change set']]
> +                                             ifNone: []) ifNotNil:
> +             [:destroyItem| | item |
> +             aMenu removeMorph: (item := aMenu submorphs last).
> +             aMenu addMorph: item after: destroyItem].
> +     ^aMenu!

Can you explain what you want to achieve
and how I can make this more convenient?

We can talk this over when we meet in Palo Alto, but the idea is an important one, and I'm paying for having been too lazy to write it up properly.  Let me try and give a quick sketch here.

The goals are to

- allow package load to augment menus without the original definitions of those menus knowing anything about the subsequently loaded packages.
- to allow menus to be augmented with single actions defined in methods that implement those actions
- and, depending on menu implementation, either
  - if menus are created every time a user invokes a menu, then to simply include the relevant extensions in the menu
  - if menus are stored in variables, to automatically construct, or reconstruct the menu when either loading or unloading of a package changes the items in a menu

We design menu pragmas in action methods to specify
- the (name of the) menu to be extended
- the text of the menu entry
- information regarding what group of items the menu item belongs with
- information regarding the menu item's relative order with respect to other elements in the group

Rationale:
With this specification a package can extend any number of menus in tools simply by being loaded, with no collisions with any other packages defining extensions on those menus.  Tools become freely pluggable, and system configurations constructed from different sets of loaded packages are decoupled; we don't need many menu definitions, just an initial base menu which is extended with the current set of extensions.

For this to work we need to "name" menus, and to use some numbering scheme to define groups (menu entries between lines) and elements within each group.  One simple scheme is to use numbers:
- the definitions of initial base menus number groups, so that the first group (the items before the first line) is numbered group 10, and the second group 20, and so on, allowing extensions to specify new groups by using group numbers that are not a multiple of 10
- the definitions of entries within groups are numbered, again in multiples of 10, so that the extension can fit anywhere in the group 

So given
MenuMorph fromArray: {
{'find...(f)' translated. #find}.
{'find again (g)' translated. #findAgain}.
{'set search string (h)' translated. #setSearchString}.
#-.
{'do again (j)' translated. #again}.
{'undo (z)' translated. #undo}.
#-.
{'copy (c)' translated. #copySelection}.
{'cut (x)' translated. #cut}.
{'paste (v)' translated. #paste}.
{'paste...' translated. #pasteRecent}.
#-.
{'set font... (k)' translated. #offerFontMenu}.
{'set style... (K)' translated. #changeStyle}.
{'set alignment...' translated. #chooseAlignment}.
"
#-.
{'more...' translated. #shiftedTextPaneMenuRequest}.
"
}

you could imagine the following numberings:

    10.01    find
    10.02    findAgain
    10.03    setSearchString
-
    20.01    again
    20.02    undo
-
    30.01    copySelection
    30.02    cut
    30.03    paste
    30.04    pasteRecent
-
    40.01    offerFontMenu
    40.02    changeStyle
    40.03    chooseAlignment

So I can specify e.g. a new group inserted before the first one by using, e.g. 5.005 as an index, and can slot an item between again and undo using 20.015, etc.

This gives us menu pragmas that look like:

TextEditor methodsFor: '*SpellChecker-extensions' stamp: 'mad hacker 9/9/1999'
spellCheck
    <menuAction: #yellowButtonMenu
      label: 'spell check selection (s)'
      position: 10.035>
    ...code implementing spell checking...

(note that the action, #spellCheck, is implicit, it is the selector of the method containing the pragma)

and
  - if menus are created every time a user invokes a menu, then search for pragmas within the relevant class hierarchy, compute, sort and insert individual extensions to the menu 
  - if menus are stored in variables, to have compilation and method removal send a message to the class to/from which method(s) are added/removed so that the class can recompute menus (as in the line above) when code is added/removed.

What I saw in ChangeSorter was quite different.  It seems to be a way of specifying entire menus, and I'm not sure how these menus are to be combined.  Maybe I'm misunderstanding the way the scheme is supposed to work.  What I've described above is very close to the one that pragmas came from in the first place, which was my attempt to decouple the components that could be loaded into VisualWorks when we decomposed the system into easily loadable parcels.  Up until that point VisualWorks had had all its tool menus predefined, disabling items that were to do with components delivered as file-ins that weren't yet filed-in.  It was too rigid.  It didn't allow for future expansion.  And so I had the idea of menu pragmas to decouple things.  Steve Dahl then came up with the scheme to define a base menu, number its items appropriately, and extend the menu.

One of the things that's really nice about the VisualWorks scheme is that the menu pragma itself is actually implemented (remember that pragmas are Message instances with literal parameters).  The class MenuBuilder (IIRC) implemented various menu pragma methods so the patten is

- in the method that defines the base menu, define the base menu, create an editor on it, ask the editor to collect the pragmas and augment the menu with those found
- the menu editor then collects the menu pragmas and then performs each one to collect the information from it

So one can find other menu pragmas using senders, and find the editor using implementors, and one can extend the scheme by adding additional methods to MenuEditor, again possibly loaded from packages.


HTH

_,,,^..^,,,_
best, Eliot