> would it be a great effort to create a new type of link, that points
> to a page in a different branche of the tree? I would like to do
> something like this:
>
> SmallWiki 2
> |-Page 1
> |-Page 2
> |- Page 3 (This page has a Link to the page "SmallWiki 2")
>
> Perhaps a *singelton:SmallWiki 2* tag? :-)
No, but you have full support of absolute and relative links simulating
the unix file-system. In your case you could chose from any of the
following:
absolute: */* or nicer */>Back 2 Root*
relative: *../..* or nicer *../..>2 Levels Up*
Cheers,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
>> In my opinion the properties of the Seaside component should be stored
>> in the structure. The description for this could be built from the
>> command object (SW2EditComponentCommand) that is dynamically enhanced
>> with the description of the currently selected component class.
Okay, this is now in the latest code, load Magritte-All-lr.11 and
SmallWiki2-All-lr.66. Just to be sure, reinitialize the environment and
try out the new settings command on the Counter and the Tree-Widget.
However there are not that many possible settings yet, but now it is
just a matter of writing some descriptions and we will soon have more
flexibility as we had in SmallWiki 1 with the templates. I also fixed
some other bugs all over SmallWiki.
> Right now I'm trying to edit the count of a WACounter (added a
> descritption). I know Seaside2 components just live for the session but
> that's not a problem for now.
>
> We can store arbitary objects in dictionary in the user. So we can
> write a
> structure that has a string and uses this as a key to fetch an object
> from
> the current user. I want do display and edit them. So we can pretend
> we edit persistent objects instead of seaside components.
>
> Fine with me. Just how do I do that? I tried something like
>
> MyComponent class>>descriptionModel
> ^ MADynamicObject on: [
> SW2CurrentContextHolder value contents in: [ :context |
> (context componentFor: context structure) in: [ :component |
> component description ] ] ].
>
> but that didn't work.
Okay, I see, you are probably not interested too much into the stuff I
wrote above :-)
Even-tough I again tried hard to understand what you want to do with
the above code, I could not get it. Mhh, so I guess that you want to
know how to use a description on a different model than it has been
defined on?
Answer: Suppose you have aDescription and aModel from anywhere in your
image, you can plug them together and get a Seaside component by
sending:
aDescription asComponentOn: aModel
>> Another thing I don't like in your code is that you don't store the
>> modifications in the command object. This means that the changes won't
>> be logged.
>
> Yes, right. This was thought to be a proof of concept prototype, not
> the
> final version. But how should I do that? Add a Dictionary and override
> #doesNotUnderstand?
Magritte is always doing a dispatch over the model using #readUsing:
and #write:using:, so you should override those. See their implementors
for some more documentation.
Cheers,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
Hi,
i search to create a new file in smallwiki but i can't.
Can you give me one simple example to try in workspace,please.
I've tried with this,but it doesn't work:
writeFile
| aNewFileStream anEncodedStream |
aNewFileStream := NewFileStream
createFile: 'C:\testutf.txt' mode: #binary
onError: [].
anEncodedStream := EncodedStream on: aNewFileStream
encodedBy: UTF8StreamEncoder new.
anEncodedStream nextPut: (Character unicodeValue: 65279).
anEncodedStream nextPutAll: ( '125,00 ').
anEncodedStream nextPutAll: ( 'test ').
aNewFileStream close.
readFile
| aNewFileStream anEncodedStream aString |
aNewFileStream := NewFileStream
on: (File open: 'c:\testutf.txt') mode: #binary.
anEncodedStream := EncodedStream on: aNewFileStream
encodedBy: UTF8StreamEncoder new.
anEncodedStream next.
"Skip header(BOM; for example, FF FE ..)"
aString := anEncodedStream nextString.
aNewFileStream close.
aString out.
cheers
Gianluca
____________________________________________________________
Navighi a 4 MEGA e i primi 3 mesi sono GRATIS.
Scegli Libero Adsl Flat senza limiti su http://www.libero.it
> Now that we can add arbitrary Seaside2 components in SmallWiki2, I'd
> like to
> be able to edit them. I initially though that'd be quite simple. Just
> add a
> description to my components and do something like this:
>
> MyCommand>>asComponent
> | comp |
> comp := self context componentFor: self structure.
> ^(comp asComponent)
> "addValidatedForm: #( save cancel );"
> addDecoration: (MAFormDecoration buttons: #( save cancel ));
> addDecoration: (SW2ValidationDecoration new);
> yourself.
>
> This works until I press the save button. Then somehow my Seaside2
> component
> ends up as structure in the context.
I don't really understand what you try to do :-/
After all the component instance you are requesting by calling
#componentFor: is only existing during the current session. Don't you
want to have something more persistent?
In my opinion the properties of the Seaside component should be stored
in the structure. The description for this could be built from the
command object (SW2EditComponentCommand) that is dynamically enhanced
with the description of the currently selected component class.
Another thing I don't like in your code is that you don't store the
modifications in the command object. This means that the changes won't
be logged.
In general: Never write to the model directly, always use the command
pattern, else your changes will be lost.
Cheers,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
Hi Daria,
> Wir wollten gerade als Beispiel/Test für das Refactoring das Löschen
> von allen externen Links auf einer Seite implementieren. Dabei haben
> wir festgestellt, dass es keine Möglichkeit gibt, aus einem Container
> (z.B. SW2DocumentGroup) ein "Kind" zu entfernen, da children ein Array
> ist und das remove nicht zulässt. Wir dachten daran, Array durch eine
> Collection zu ersetzen, was aber nicht ohne weiteres funktioniert.
> Hast Du eine Idee, wie wir das lösen können?
what about
self setChildren: (self children
copyWithout: aChild).
and
self setChildren: (self children
copyWith: aChild)
?
The rational of using arrays is that they are ways more space and time
efficient than ordererd collections. Modifications to the parse tree
are usually rare, the current code mostly just rebuilds the document.
I suggest that you add the code snippets avove as extension methods
#add: and #remove: to the composite of the document hierarchy.
One thing you have to take care is that some document nodes require a
parent information, like the internal links to do the update. So if you
add new links you have to set the owner somehow, unless they won't
work.
Cheers,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
> Is ther a way to ask for user input when I'm allready in the doValidate
> or doExecute method?
No, no way to do that.
Commands should be atomic and are execute within a critical section. If
you would have user interaction in there you would run into two
problems:
1. The separation of the model (Command-Pattern) and the GUI (Seaside)
would be broken.
2. When using Seaside as GUI the user could use the back- and
forward-buttons and therefor destroy the atomic execution of the
command.
Again two possible solutions for this:
1. You raise an exception/notification in #doValidate to check for
notify the GUI about the fact that there is a password required and
then resume the validation.
2. You put a password field right into your command that can be left
empty. #doValidate raises an exception if the password is missing or
wrong.
Hope this helps,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
>> Another powerful thing is the MADynamicObject class, that
>> allows to define descriptions where you don't know the
>> possible properties in advance. Try something like:
>>
>> B class>>optionsToBeUsed
>> ^MADynamicObject on: [ 1 to: 100 atRandom ].
>
> Sorry, I don't understand how this is then dependent on the instance,
> because this is still on the class side, no?
Okay, in your case there is no ready made solution. Though, it is a
very interesting problem to investigate.
Just to explain where this problem is coming from: Basically I decided
to have no blocks in the descriptions to get an certain uniformity in
the interface. Of course it would be possible to have an option-block,
but then maybe later on I also want to have a dynamic nil-label-block,
and a default-block, ... and nobody knows where that should stop. What
is more, blocks are generally a bad thing to serialize, in most of the
cases they are not serialize-able at all, and I don't want to spoil
ability to serialize description objects.
Load the latest version of Magritte (Magritte-All-lr.10) and then there
are two different solutions to your problem:
1. Do you descriptions on the instance side of your class exactly as
you did on the class side but using the current state of the object.
Then override the message #description with the following snipped of
code:
MyModel>>description
^MABuilder default build: self.
2. Load the latest version of Magritte (Magritte-All-lr.9) and use
MAModelObject, it is similar to MADynamicObject but tries to pass into
the block the instance of the model. I suggest not to use it, unless
you really know what you do. Two more warnings: (1) Debugging code
using this dynamic object can be very nasty. (2) Don't have a look at
the code if you are easily scared.
A class >> descriptionElements
^(MAOptionsDescription selector: #foo)
options: (MAModelObject on: [ :model | model zork ];
yourself.
The first solution I presented seems to work in all cases and to be
much more clean. Try to use this one, if you don't have a reason not to
do so! However the second solution is something that main-stream
languages can't do and therefor it is cool :-)
Does anybody has a third solution?
Cheers,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
Hi David,
> There's probably a bug in SW2PluggableComponent>>renderContentOn:
> This class has a block as an inst var and in #renderContentOn: this
> block is
> analyzed if it expects two args. If not, it's tried to render this
> block
> with html render: block. But this won't work, because a block can't be
> rendered directly.
well what do you do with your all your div, span, heading and
anchor-tags? There are blocks that are rendered all over the place :-)
html div: [
html span: [
html heading: [
html
anchorWith...
do: [ ... ] ] ] ].
Have a look at WAAbstractHtmlBuilder>>render: and
BlockContext>>renderOn: where the double dispatch on blocks happens. As
you can see Seaside accepts zero and one argument blocks, and I
enhanced this for SW2PluggableComponent to have two possible arguments.
However it is generally not a very good idea to use
SW2PluggableComponent extensively, but for fast prototyping its use
might be nice. Currently there is no use of SW2PluggableComponent in
SmallWiki2 anymore.
> Another issue is that the style-sheet is stored in a remote file which
> we
> could not change/extend. Wouldn't it be better to have the style
> definitions
> directly in the image? For instance you could create a style library
> class
> for SW2.
Please submit a patch to SmallWiki2-Seaside, I just didn't bothered to
put all those style-sheets and images into a style library class yet,
it was simply easier for me to edit the file in a css-editor. Check out
the new style, it has some fancy css-buttons in the heading-bar!
> Then I have encountered a problem with the commands for a structure. I
> have
> created a new subclass of Structure and now I would like to define some
> commands for this new kind of structure. But then all the other
> commands
> that are bound to Structure (like Move, Copy, Add, ...) will also be
> displayed in the command widget when browsing an instance of this new
> structure. I see no way to specify that these commands should not be
> available for my newly defined structure. It would be better to have
> the
> possibility to explicitly say for which structures a command should be
> available. A collection of structure classes instead of SW2Command
> class >>
> defaultStructureClass maybe?
I see the problem, but having collection the commands (static state)
wouldn't solve the problem either, because one cannot know what
structure and commands (it is an m to n relationship) will exist in the
future. It also gets difficult because one doesn't know who has the
responsibility to register the commands, the command or the structure?
Generally I prefer dynamic state, that means we should introduce
another dispatch in SW2Context>>allValidCommands to let the command and
the structure have the possibility to reject a command.
> Another problem with newly created subclasses of Structure is that
> they will
> all appear in the 'type'-dropdown when adding a child structure with
> the
> AddCommand. This might not be desired for all subclasses of Structure.
Similar problem as above: I suggest that you submit a patch to the
latest SmallWiki2 package that fits your needs so that it can be merged
into the core code and everybody can profit.
> It would be great to have a method MAElementDescription >>
> attributeAt:put:
> to specify new attributes for the component of a description.
> Currently, one
> has to use #attributes which is not convenient.
Margritte is not a Seaside framework, generally speaking.
As far as I know there is just one use of #attributes: in SmallWiki
itself and as I don't write code that I don't need, I didn't felt the
need for such methods yet. However feel free to add them for your
convenience, that's the reason why there are class extensions ;-)
> Then there are several components available that render a text field
> with a
> button, such as MADateInputComponent, MATimestampInputComponent, ... I
> tried
> to create a subclass of such a component to change the button's
> appearance
> (different label or an image as button). But this is not possible
> because
> the button is rendered directly in #renderEditorOn:, so I can't
> override
> this method. It would be better to have a method #renderButtonOn: in
> MATextInputComponent, so all subclasses with a button have to override
> just
> this method which would be empty in MATextInputComponent.
Yeah, I see, maybe sometimes I am too lazy.
> But besides that, Magritte is really cool. :)
Thanks.
Cheers,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
> Das mit dem Compilieren hat ja jetzt geklappt. Aber unser eigenes
> Widget wird nicht in der Drop Box aufgelistet? Nach welchen Kriterien
> wird da gesucht? Unser Widget erbt von SW2Widget. Es klappt nicht wenn
> wir es in einem eigenen Package haben oder sogar im
> SmallWiki2-Seaside-Widgets Package.
Have a look at the following snippet of code and check for the
conditions ;-)
SW2EditComponentCommand class>>descriptionComponentClass
^(MAOptionsDescription selector: #componentClass label: 'Component
Class' priority: 200)
options: (MADynamicObject on: [
Array streamContents: [ :stream |
SW2Widget allSubclassesDo: [ :each |
each isAbstract
ifFalse: [ stream nextPut: each ] ].
WAComponent allSubclassesDo: [ :each |
each canBeRoot
ifTrue: [ stream nextPut: each ] ] ] ]);
beRequired;
yourself.
Cheers,
Lukas
--
Lukas Renggli
http://www.lukas-renggli.ch
> I have a basic question about commands.
> When you click on the edit link you get
> a special edit page.
SW2Command>>asComponent (*)
Usually this just returns a magritte component built automatically from
the description of the command, but as you can see in SW2ViewCommand
one can also override it to return any other Seaside component.
> Shouldn't there be something like this somewhere:
> html anchorWithAction: [SW2EditCommand>>doExecute] text:
> SW2EditCommand asLabel
This is something else, you can create a link to a structure and
command anywhere using:
html
anchorToStructure: aStructure
command: aCommand
do: aBlock (*)
Cheers,
Lukas
(*) Check the exact wording in your own image, i don't have access to
one right now.
--
Lukas Renggli
http://www.lukas-renggli.ch