I can rotate a TextMorph in Morphic but cannot find the method for rotating it. I want to use it during initialization.
Try this:
aTextMorph addFlexShell rotationDegrees: 45.0
#addFlexShell wraps the TextMorph in a TransformationMorph that can be used to apply the transformations. When you apply the rotation via a morph's halo, it also adds the TransformationMorph. You may want to store it in a variable to access it again later:
flexShell := aTextMorph addFlexShell.
flexShell rotationDegrees: 45.0.
"..."
If you write this in a method and you need the flex shell (for transformation purposes) after the method has ended, add an instance variable to your class and save the flex shell in it:
Object subclassNamed: #MyClass
instanceVariableNames: 'transformationOfMyMorph myMorph'
classVariableNames: ''
poolDictionaries: ''
category: 'MyPackage'
myMethod
myMorph := TextMorph new contents: 'rotated text'.
transformationOfMyMorph := myMorph addFlexShell.
rotateFurther
transformationOfMyMorph rotationDegrees: transformationOfMyMorph rotationDegrees + 5.0.
If you only need the flex shell in one method, use a temporary (local) variable:
myMethod
| flexShell |
myMorph := TextMorph new. "..."
flexShell := myMorph addFlexShell.
"..."
Related
I am completely new to Pharo, Smalltalk. I'm developing a small app that will convert temperature from Fahrenheit to Celsius. Can anyone give me any idea on how to create an input field using TextMorph and display it on a window as shown in the screen shot. In addition, being able to get the data back from the input field when the button is clicked. The below code is what I have done so far.
Screenshot
The class TemperatureMorph
BorderedMorph subclass: #TemperatureMorph
instanceVariableNames: 'tempInputField counter'
classVariableNames: ''
package: 'Assignment'
The initialize method: Contains a label, textbox and a button.
initialize
| headingLabel converterButton|
super initialize.
self bounds: (0#0 corner:300#300).
self color: Color gray.
headingLabel := StringMorph contents: 'Converter'.
headingLabel position: 130#20.
self addMorph: headingLabel.
tempInputField := TextMorph new.
tempInputField position: 50#50.
self addMorph: tempInputField.
Thanks
On a side not, if you're doing UI stuff in Pharo for anything other than learning (It looks like OP /is/ learning, so this probably doesn't apply). You should be looking at either Glamour or Spec. Both of which have really easy text input and control systems.
Spec
Glamour
You can already see the necessary code in your screenshot, you only have to replace the construction of a StringMorph with that of a TextMorph. I suggest you take a look at the Pharo by Example book. It has a chapter on Morphic, which is the UI framework in Pharo.
yourTextMorph := TextMorph new.
yourTextMorph contents: 'initial text'.
ownerMorph addMorph: yourTextMorph.
I guess you will also want to read the contents back out of the TextMorph. You can use yourTextMorph contents to achieve that. See also Pharo Smalltalk: Reading from TextMorph
Just like with other objects, you can call:
set('myKey', 44);
set('something', 'Hello World');
you can even do maps
set("myMap", new Map());
but how do i call set to notify if a map property has changed. Obviously, i cant do:
set('myMap.myProp', 'test');
can i?
im trying to update the map property for something bound to the screen, but i thought it would be silly to do something like:
Map m = myMap;
m['myProp'] = 'test';
set('myMap',m);
since it is doing a lot of work it wouldnt need to do.
This is in PolymerDart
As far as I know this
set('myMap.myProp', 'test');
should work fine to add an item to the map with key myProp and value 'test'
Is it possible to parse Block through flex and bison??
Example:
Suppose
BEGIN BLOCK BLK_ROWDEC
NAME cell_rowdec
SIZE UNI_rowdecSize
ITERATE itr_rows
DIRECTION lgDir_rowdec
STRAP STRD1,STRD3,STRD2
WRAP WRD1
VIA VIAB,VIAC,VIAD
ENDS BLK_ROWDEC
Now I want to check Is BEGIN and END is belong to same block or not?/Is it possible with flex and bison
Yes it's possible, just save the block name with the BEGIN and check it when you get the END.
But the block name is redundant here, and Bison will match up begins and ends automatically. If you can remove it from your syntax I would do so.
Delphi XE6 - I have a set. I would like a simple way to turn ALL elements off. i.e. instead of Exclude, something like ExcludeALL. I have tried to loop through all elements, but I get an error.
Code
type
TSearchParametersType =
(smDUNSAvailable = 1,
smDUNSHit,
smDUNSMiss,
smDUNSAbsent,
smRegistryAvailable,
smRegistryHit,
smRegistryAbsent,
smRegistryMiss,
smNameAvailable,
smNameHitExact,
smNameHitWords,
smNameMiss
);
// Now create a set type, where we can have a variable that has all the values of TSearchParametersType
type
TSearchParametersSet = set of TSearchParametersType;
...
var
i : Integer;
sSearchStatus: TSearchParametersSet;
begin
for i := smDUNSAvailable to smNameMiss do
Exclude(sSearchStatus, i);
The error I get is "Incompatible Type: 'Integer' and TSearchParametersType. "
Is there a simple way to Exclude ALL, other than MANUALLY going through every element?
Thanks
From the documentation:
Every set type can hold the empty set, denoted by [].
So you can assign the empty set to your variable like this:
sSearchStatus := [];
FWIW, your code fails because smDUNSAvailable and smNameMiss are of type TSearchParametersType and so not compatible with the variable i which is of type Integer. In order to make your code work you would need to change the loop variable to be of type TSearchParametersType.
Let me start by saying that David's answer is the correct one.
I'll just post another one to show how you could do it manually. This code might come in handy some other time:
var
sSearchStatus: TSearchParametersSet;
SearchParametersType : TSearchParametersType;
begin
sSearchStatus := [smDUNSHit, smDUNSMiss, smDUNSAbsent, smRegistryAvailable, smRegistryHit];
for SearchParametersType := low(TSearchParametersType) to high(TSearchParametersType) do
Exclude(sSearchStatus, SearchParametersType);
end;
Based in the users selection on the TASK Wizard page, I need to be able to use the answer to create 5-different variables/variant to use in the FILES & ICONS sections.
Examples;
1.- Results would indicate what directory to place files into.
2.- Results would also indicate what the TEXT in the Perameters would be.
Each example above would be a different variable/variant
These variants would essentially replace #define(s) variable that I am currently using.
My application is a multi-state application with each state having different support file contents, I wish to be able to use the TASK option instead of having a separate exe file for each.
Your question is too broad to cover, so I'll try to show you just a principle of getting [Files] entry DestDir parameter from script code, which is what you can apply also for [Icons] parameters. The key is to use the {code:...} constant in which you can specify a getter function declared in the [Code] section of your script. The following example shows, how to install file into 4 different directories based on selected tasks:
#define PathNone "None"
#define PathBoth "Both"
#define PathFirst "First"
#define PathSecond "Second"
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Tasks]
Name: TaskFirst; Description: "First task"
Name: TaskSecond; Description: "Second task"
[Files]
Source: "MyApp.exe"; DestDir: "{code:GetMyAppDir}"
[Code]
function GetMyAppDir(Param: string): string;
begin
// check if both tasks are selected; if yes, then assign a subfolder path defined
// by the PathBoth preprocessor variable to the Result
if IsTaskSelected('TaskFirst') and IsTaskSelected('TaskSecond') then
Result := '{#PathBoth}'
else
// both tasks are not selected, so let's check if the first one is; if yes, then
// assign the PathFirst preprocessor variable to the Result
if IsTaskSelected('TaskFirst') then
Result := '{#PathFirst}'
else
// first task nor both are selected, so let's check if the second one is; if so,
// assign the PathSecond preprocessor variable to the Result
if IsTaskSelected('TaskSecond') then
Result := '{#PathSecond}'
else
// no task is selected (this is the last possible situation), let's assign the
// PathNone preprocessor variable to the Result
Result := '{#PathNone}';
// finally prepend to the Result the {app} constant and expand all the constants
Result := ExpandConstant('{app}\' + Result);
end;
Similar you can do with many section parameters, but not all (this is quite a broad topic). Beware also, that some of the parameters are evaluated eariler (when the tasks were not yet seen by the user), some of them later. Also some of the parameters are evaluated more than once (assigned getter functions may execute more than once).
So it depends which parameters are you going to specify that way. For your mentioned [Files] section DestDir parameter and [Icons] section Parameters parameter you are fine with this approach.