Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!sun-barr!newstop!sun!stpeter!cmcmanis From: cmcmanis@stpeter.Sun.COM (Chuck McManis) Newsgroups: comp.sys.amiga Subject: Re: Gadgets Message-ID: <129588@sun.Eng.Sun.COM> Date: 23 Dec 89 00:15:55 GMT References: <1989Dec20.100023.6376@cat.fulcrum.bt.co.uk> Sender: news@sun.Eng.Sun.COM Reply-To: cmcmanis@sun.UUCP (Chuck McManis) Organization: Sun Microsystems, Mountain View Lines: 123 In article <1989Dec20.100023.6376@cat.fulcrum.bt.co.uk> (Simon Raybould) writes: > I am trying to make two boolean gadgets mutually exclusive of each > other The code below works ish. When the first gadget is selected, it > is highlighted. When the second gadget is selected, it is highlighted > and the first should be un-highlighted as a toggle where one or the > other is highlighted, but not both. OK there are a few things that will help you out considerably. The first is to set up your gadgets correctly. The flags you will need are, GADGIMMEDIATE, and GADGHCOMP. The gadget *must* be of type Image or not have any IntuiText in it. The reason for the restrictions are that Intuition has a tough time figuring out how to render multiple graphic items such as a gadget with Text and a border(s) structure. The other thing you need to do is stop using the RefreshGadgets()/AddGadgets() calls and use RefreshGList/AddGList ones in 1.2. The latest ROM Kernel Manual AutoDocs and Includes has the documentation for them in them. >I believe that to do this, the gadgets have to be removed, altered and then >re-added to the window, is this true? Not necessarily, but you can if you choose to. >The code below is taken from a program and is from the code for handling >the GADGETUP message. PURCHASE and REPAY are both gadget structures. Ok and now a step by step analysis : > } else if(Message->IAddress == (APTR)&REPAY) { This is not the optimal way to identify gadgets, using their GadgetID is much better. When you create the gadget, set the ID to something useful like g->GadgetID = REPAY_GADGET; Then in your code you can use something like : case GADGETUP : thisgad = (struct Gadget *)(Message->IAddress); switch (thisgad->GadgetID) { case REPAY_GADGET : ... etc ... > PR = PR_REPAY; > ip = RemoveGadget(AddWindow, &PURCHASE); > ir = RemoveGadget(AddWindow, &REPAY); This will work, but add the following code : PURCHASE.NextGadget = &REPAY; REPAY.NextGadget = NULL; > REPAY.Flags |= SELECTED; > PURCHASE.Flags &= ~SELECTED; This is fine. > AddGadget(AddWindow, &PURCHASE, ip); > AddGadget(AddWindow, &REPAY, ir); Now instead of this, use the code : AddGlist(AddWindow, &PURCHASE, -1, 2, NULL); This will add your two gadgets back in one call. > RefreshGadgets(&REPAY, AddWindow, NULL); Now instead of the RefreshGadgets call use this instead : RefreshGList(&PURCHASE, AddWindow, NULL, 2); > } else if(Message->IAddress == (APTR)&PURCHASE) { > PR = PR_PURCHASE; > ir = RemoveGadget(AddWindow, &REPAY); > ip = RemoveGadget(AddWindow, &PURCHASE); > PURCHASE.Flags |= SELECTED; > REPAY.Flags &= ~SELECTED; > AddGadget(AddWindow, &REPAY, ir); > AddGadget(AddWindow, &PURCHASE, ip); > RefreshGadgets(&REPAY, AddWindow, NULL); > } Clearly the same comments apply here as well. Now another way for this to work is to maintain a pointer to the currently selected gadget, of a mutually excluded gadget list. A pointer to this pointer is stored in the UserData field of the gadgets that are excluded. So lets say you had three gadgets {Foo, Bar, and Bletch} that were all mutually exluded. Declare a pointer "FBBPointer" or something and set it up to Point at the initially selected gadget. Now when ever you see a gadget select you can process it as follows : case GADGETUP : g = (struct Gadget *)(Message->IAddress); if (g->Flags & MUTUALEXCLUDE) { /* Find the currently selected gadget of the group */ g1 = *((struct Gadget **)(g->UserData)); if (g != g1) { /* Simple optimization */ /* Deselect the current one */ g1->Flags &= ~SELECTED; /* Select the one the user clicked on */ g->Flags |= SELECTED; RefreshGlist(g, AddWindow, NULL, 1); RefreshGlist(g1, AddWindow, NULL, 1); *((struct Gadget **)(g->UserData)) = g; } } break; This method has a couple of advantages. One, this same code can handle lots of different groups of excluded gadgets, and two the variable you use to keep the selected gadget pointer can be used by your program as a state variable. And finally, there isn't any reason why you have to limit yourself to a a pointer to a gadget. Let's say you were designing a backup program and had two gadgets "DF0:" and "DF1:" You could create a structure that looked like this : struct activedrive { struct Gadget *ActiveGadget; char *DriveName; } *FooBarBletch; Now you use the above code, which would keep FooBarBletch pointing at the correct gadget, and when it came time to open the disk that was selected you could use something like : Lock(FooBarBletch->DriveName, ACCESS_WRITE); Because the FooBarBletch pointer would already have the pointer to the appropriate gadget in it. Just some ideas .... --Chuck McManis uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@Eng.Sun.COM These opinions are my own and no one elses, but you knew that didn't you. "If it didn't have bones in it, it wouldn't be crunchy now would it?!"