1. +Help!
- Posted by CAMPOS ARRIBAS- LUIS RAUL <95203695 at XAEE.UB.ES> May 08, 1998
- 685 views
Hi everybody! Can someone explain me with accuracy and simplicity how can i make 'clickeable' by the mouse a certain area of a text- mode screen? Imagine that i have the text 'Quit' at position (10,10).I've tried to figure out Jiri Babor's textmenu.e but it's quite complex for me! see ya!:) - Luis - (no more dosshell!i have already installed the cool-looking Norton Commander)
2. Re: +Help!
- Posted by David Cuny <dcuny at DSS.CA.GOV> May 08, 1998
- 1256 views
Luis wrote: > Can someone explain me with accuracy and simplicity how can i > make 'clickeable' by the mouse a certain area of a text > mode screen? In graphics or text mode, it's pretty simple. The process is called "hit = testing". Whenever there's a mouse event, you have to check to see if = it's hit anything, typically by checking if it fell within some = boundary. For example, the text "Quit" at {10,10} falls within a bounds rectangle = of {{10,10},{14,10}}, because the text is 4 characters across (10+4-1) = and 1 character high (10+1-1). Notice I subtracted 1 from both values, = because we are using {1,1} as the offset of our coordinates, instead of = {0,0}. The point falls into the bounding rectangle if it is greater or equal to = the upper-left hand corner, and less or equal to the lower-right hand = corner. It looks something like: if mouse_click() then -- simplified -- greater or equal to the upper left corner if mouse_x >=3D 10 and mouse_y >=3D 10 -- less or equal to the lower right corner and mouse_x <=3D 14 and mouse_y <=3D 10 then -- the user pressed "Quit" end if =20 end if You could write this as a routine: function in_bounds( sequence mouse, sequence p1, sequence p2 ) -- returns true if mouse inside rectangle defined by p1, p2 return -- returns true if all tests are true mouse[1] >=3D p1[1] -- upper left x and mouse[2] >=3D p1[2] -- upper left y and mouse[1] <=3D p2[1] -- lower right x and mouse[2] <=3D p2[2] -- lower right y end function =20 Here's a call to the function: if mouse_click() then if in_bounds( mousePos, {10,10}, {10,14} ) then -- "quit" clicked end if end if For handling several buttons on the screen, you could save the buttons = in a sequence, such as: constant Owner =3D 1, Title =3D 2, P1 =3D 3, P2 =3D 4 sequence buttons =3D { { 1, "Quit", {10, 10}, {14, 10} }, { 1, "Help", {16, 10}, {20, 10} } } =20 The routine would then look at each button to see if it had been = pressed: =20 -- mouse click? if mouse_click() then -- look at each button button =3D "" for i =3D 1 to length( buttons ) do -- was this button hit by the mouse? if in_bounds( mousePos, button[i][P1], button[i][p2] ) then -- save the button name button =3D button[i][Title] -- leave the loop exit end if end for end if If you wanted to add windows to your application, it would be a little = bit more complex, but not much. Because windows can overlap, you need to = test the closest window first: +----------------+ | window 2 | | | | +--------------+ | | window 1 | | | | | | | | X | | +----|-----------+ | | | +--------------+ As you can see (if you are looking at this with a fixed-width font), the = "X" is a point shared by both windows. Which window does it belong to? = The answer is: whichever window is tested first: +----------------+ | window 2 | | | | +--------------+ | | window 1 | | | | | | X | +----| | | | +--------------+ If you test window 1 first (because it's the first window), then it gets = the mouse hit. The order of the windows is called the "z order". The "z" = refers to the third dimension (depth).=20 When you draw the windows, you draw them in reverse z order, so the = first windows ends up on top of all the rest. Once you know which window is hit, you then do the button test on each = button in the window to see which button, if any, was pressed. So the = logic looks something like: if the mouse is pressed, then check windows in z order for a hit if a window was hit, then if that window wasn't on top, then put it on top else if a button in the window was hit then do that action end if end if end if end if That's more or less what the inner loop of a windowing system looks = like. I've included a simple windowing program at the end of this = e-mail. There are a number of differences in the code: - The second window point is a relative size, not a screen point - The button position is relative to the window's {2,2} position - The button size is calculated on the text size A major bit that is missing here is the clipping routines. When you = write into a window, any text that doesn't fit should be clipped, such = as: +----------------+ | In a real windo| | | | | +----------------+ instead of this: +----------------+ | In a real window, this wouldn't look like this. | | | | +----------------+ But I needed to leave *something* for you to do. Hope this helps! -- David Cuny -- HERE'S THE CODE! -- textwin.e -- simple text windows include mouse.e -- attributes constant Owner =3D 1, Title =3D 2, P1 =3D 3, P2 =3D 4 sequence buttons, windows, z_order -- define some buttons buttons =3D { { 1, "< Quit >", {1, 1} }, { 2, "< Help >", {1, 1} } } -- define some windows windows =3D { { 1, "Window 1", {3, 3}, {17, 17} }, { 1, "Window 2", {10, 10}, {40, 15} } } -- the drawing order of the windows z_order =3D { 1, 2 } =20 integer key, clicked sequence mouse_pos object mouse function remove( object o, sequence s ) -- remove all instances of o from s sequence s2 =20 =20 -- empty list s2 =3D {} =20 =20 -- go though list for i =3D 1 to length( s ) do -- if NOT a match if compare( s[i], o ) then -- add to list s2 =3D append( s2, s[i] ) end if end for =20 =20 return s2 =20 end function procedure put_on_top( integer window ) -- place window first in z order =20 =20 -- remove from list z_order =3D remove( window, z_order ) =20 -- place first z_order =3D prepend( z_order, window ) =20 end procedure procedure draw_button( integer button ) -- draw button in owner's window =20 integer owner sequence at, ownerAt -- get button's position at =3D buttons[button][P1] -- get owner owner =3D buttons[button][Owner] -- get owner's position ownerAt =3D windows[owner][P1] =20 -- add to owner's position, and adjust at =3D at + ownerAt =20 -- position position( at[2], at[1] )=20 =20 -- text puts( 1, buttons[button][Title] ) end procedure procedure draw_buttons( integer owner ) -- draw buttons in windows -- buttons are relative to the owner's position =20 -- look though all the buttons =20 for i =3D 1 to length( buttons ) do -- owned by this window? if buttons[i][Owner] =3D owner then -- draw the button =20 draw_button( i ) end if =20 end for end procedure procedure draw_rect( integer x1, integer y1,=20 integer cx, integer cy ) -- draw top position( y1, x1 ) puts( 1, "+" & repeat( '-', cx-2 ) & "+" ) -- draw middle for y =3D y1+1 to y1+cy-2 do position( y, x1 ) puts( 1, "|" & repeat( ' ', cx-2 ) & "|" ) end for =20 =20 -- draw bottom position( y1+cy-1, x1 ) puts( 1, "+" & repeat( '-', cx-2 ) & "+" ) =20 end procedure =20 procedure draw_window( integer window ) -- draw button in owner's window integer x, y, cx, cy -- get position x =3D windows[window][P1][1] y =3D windows[window][P1][2] cx =3D windows[window][P2][1] cy =3D windows[window][P2][2] -- draw a rectangle draw_rect( x, y, cx, cy ) =20 -- title position( y, x+2 ) =20 puts( 1, " " & windows[window][Title] & " " ) -- draw the buttons draw_buttons( window ) end procedure procedure draw_windows() =20 -- draw in reverse z order for i =3D length( z_order ) to 1 by -1 do draw_window( z_order[i] ) end for end procedure function in_rect( integer x, integer y,=20 integer x1, integer y1,=20 integer x2, integer y2 ) -- true if point is in rectangle return x >=3D x1 and y >=3D y1 and x <=3D x2 and y <=3D y2 =20 end function =20 function hit_window( integer x, integer y, integer window ) -- true if point is in window =20 integer x1, y1, x2, y2 =20 =20 -- window point x1 =3D windows[window][P1][1] y1 =3D windows[window][P1][2] x2 =3D x1 + windows[window][P2][1] y2 =3D y1 + windows[window][P2][2] =20 return in_rect( x, y, x1, y1, x2, y2 ) =20 end function =20 function hit_button( integer x, integer y, integer button ) -- true if point is in button integer x1, y1, x2, y2, owner =20 -- get owner owner =3D buttons[button][Owner] =20 -- button point x1 =3D buttons[button][P1][1] y1 =3D buttons[button][P1][2] =20 -- add owner x1 =3D x1 + windows[owner][P1][1] -1 y1 =3D y1 + windows[owner][P1][2] -1 =20 -- calculate size x2 =3D x1 + length( buttons[button][Title] ) - 1 y2 =3D y1 =20 return in_rect( x, y, x1, y1, x2, y2 ) =20 end function integer clicked_window, clicked_button -- draw all the controls draw_windows() -- event loop while 1 do =20 -- was the escape key pressed? if get_key() =3D 27 then exit end if -- look for mouse event mouse =3D get_mouse() -- event? if sequence( mouse ) then -- mouse press? clicked =3D and_bits( mouse[1], LEFT_DOWN ) -- adjust mouse[2] =3D mouse[2]/8 mouse[3] =3D mouse[3]/8 else -- no click clicked =3D 0 end if -- if clicked... =20 if clicked then =20 -- clear variables clicked_window =3D 0 clicked_button =3D 0 =20 -- go through windows in z order for i =3D 1 to length( z_order ) do -- hit? if hit_window( mouse[2], mouse[3], z_order[i] ) then -- save window clicked_window =3D z_order[i] =20 -- exit loop exit end if end for =20 -- hit window? =20 if clicked_window then =20 -- is it on top? if z_order[1] =3D clicked_window then -- check buttons for i =3D 1 to length( buttons ) do -- owned by window? if buttons[i][Owner] =3D clicked_window then -- hit button? if hit_button( mouse[2], mouse[3], i ) then -- save button clicked_button =3D i -- exit exit = =20 end if end if end for =20 else =20 -- put window on top put_on_top( clicked_window ) -- redraw windows draw_windows() end if end if -- display results position( 1, 1 ) if clicked_window then if clicked_button then -- put up button title printf( 1, "hit button %s",=20 {buttons[clicked_button][Title]} ) =20 else -- put up window title printf( 1, "hit window %s",=20 {windows[clicked_window][Title]} ) end if end if =20 end if =20 end while
3. Re: +Help!
- Posted by Lewis Townsend <keroltarr at HOTMAIL.COM> May 08, 1998
- 630 views
Greetings, > Can someone explain me with accuracy and simplicity how can i > make 'clickeable' by the mouse a certain area of a text- > mode screen? > Imagine that i have the text 'Quit' at position (10,10).I've > tried to figure out Jiri Babor's textmenu.e but it's quite > complex for me! > >see ya!:) > - Luis - I've never tried it on a text screen before but this should work. Ok, you know the get_mouse command? well you use that like this I think: -- untested code -- include mouse.e -- of course sequence qbutton,mouse qbutton = "Quit" position(10,10) puts(1,qbutton) mouse = get_mouse() if mouse[2]>10 then if mouse[3]>{10} then if mouse[2]<10+length(qbutton) then -- ^ --the [2] and [3] might need to be --switched on these two lines to work -- v if mouse[3]<10 then if find(LEFT_UP,mouse[1]) then run_quit_routine() --you get the idea? end if end if end if end if end if -- end untested code -- I hope this isn't too complicated and in fact there is probably a much simpler way to do it, I just haven't figured it out yet: you might use find() more and compare() but I'm not sure. I waited to see if anyone else would answer your question before I did. I didn't test this code but it should be close to working, I just wish it didn't take so many statements. Good luck, Lewis Townsend | ____ _ _ _ _ __ |\ | __/ || / | // || / __ \ | \ ||_ || //|| // || ||__\| | \ | _| || // || // || \___ \ | | \ ||__ ||// ||// || |\__|| | |\ \|___\ |_/ |_/ || \____/ | | \ \ _____ ________ | | \ \ | __ \ | __ __ | | | \ \ ||__|| |/ || \| | | \ \ | __ / || | |_____\ \ || \\ || |__________\ || || || Keroltarr at hotmail.com ______________________________________________________ Get Your Private, Free Email at http://www.hotmail.com
4. Re: +Help!
- Posted by "Ranta, Steve" <rantas at HEART.SMA.HP.COM> May 08, 1998
- 632 views
In the windows test example code David Cuny wrote in the event loop of the program: -- look for mouse event mouse = get_mouse() -- event? if sequence( mouse ) then -- mouse press? clicked = and_bits( mouse[1], LEFT_DOWN ) -- adjust mouse[2] = mouse[2]/8 mouse[3] = mouse[3]/8 else -- no click clicked = 0 end if I get a bug reported when running the program about a type mismatch with mouse[2] when the procedure hit_window is called. I was able to circumvent the problem by "flooring" the results for mouse[2] and mouse[3]. The changes to the above line result in: -- look for mouse event mouse = get_mouse() -- event? if sequence( mouse ) then -- mouse press? clicked = and_bits( mouse[1], LEFT_DOWN ) -- adjust mouse[2] = floor(mouse[2]/8) mouse[3] = floor(mouse[3]/8) else -- no click clicked = 0 end if I am very new to euphoria so I do not know if this is the best solution, but I found it let the program run without fault. Steve Ranta
5. Re: +Help!
- Posted by David Cuny <dcuny at DSS.CA.GOV> May 08, 1998
- 622 views
Steve Ranta suggested the fix: >> mouse[2] =3D floor(mouse[2]/8) >> mouse[3] =3D floor(mouse[3]/8) Sorry about that. I hadn't gotten that result when I tested it. I looked = at the code in my editor, but hadn't notice that the floor() function = was applied later. You can also write: mouse[2..3] =3D floor(mouse[2..3]/8) I tend to forget you can do that sort of thing with sequences. Thanks for the fix! -- David Cuny
6. Re: +Help!
- Posted by CAMPOS ARRIBAS- LUIS RAUL <95203695 at XAEE.UB.ES> May 13, 1998
- 673 views
> Data de tramesa: Fri, 08 May 1998 15:03:36 -0500 (CDT) > De : Lewis Townsend <keroltarr at HOTMAIL.COM> > Assumpte: Re: +Help! > A: Multiple recipients of list EUPHORIA <EUPHORIA at MIAMIU.ACS.MUOHIO.EDU> > Enviar resposta a: Euphoria Programming for MS-DOS <EUPHORIA at MIAMIU.ACS.MUOHIO.EDU> > Greetings, > > > Can someone explain me with accuracy and simplicity how can i > > make 'clickeable' by the mouse a certain area of a text- > > mode screen? > > Imagine that i have the text 'Quit' at position (10,10).I've > > tried to figure out Jiri Babor's textmenu.e but it's quite > > complex for me! > > > >see ya!:) > > - Luis - > > I've never tried it on a text screen before but this should work. > Ok, you know the get_mouse command? well you use that like this I think: > > -- untested code -- > > include mouse.e -- of course > sequence qbutton,mouse > qbutton = "Quit" > position(10,10) > puts(1,qbutton) > mouse = get_mouse() > if mouse[2]>10 then > if mouse[3]>{10} then > if mouse[2]<10+length(qbutton) then > -- ^ > --the [2] and [3] might need to be > --switched on these two lines to work > -- v > if mouse[3]<10 then > if find(LEFT_UP,mouse[1]) then > run_quit_routine() --you get the idea? > end if > end if > end if > end if > end if > > -- end untested code -- > > I hope this isn't too complicated and in fact there is > probably a much simpler way to do it, I just haven't > figured it out yet: you might use find() more and compare() > but I'm not sure. I waited to see if anyone else would > answer your question before I did. > > I didn't test this code but it should be close to working, > I just wish it didn't take so many statements. > > Good luck, > > Lewis Townsend > | ____ _ _ _ _ __ > |\ | __/ || / | // || / __ \ > | \ ||_ || //|| // || ||__\| > | \ | _| || // || // || \___ \ > | | \ ||__ ||// ||// || |\__|| > | |\ \|___\ |_/ |_/ || \____/ > | | \ \ _____ ________ > | | \ \ | __ \ | __ __ | > | | \ \ ||__|| |/ || \| > | | \ \ | __ / || > | |_____\ \ || \\ || > |__________\ || || || > Keroltarr at hotmail.com > > ______________________________________________________ > Get Your Private, Free Email at http://www.hotmail.com Hi Lewis, I tested your code and it doesn't works.There's a type-check failure that i think that i've remove it changing 'mouse' to a object. Please,check out the following code! ;) -- tested code -- include mouse.e -- of course with trace -- trace(1) sequence qbutton object mouse integer clicked mouse_events(LEFT_DOWN + LEFT_UP + RIGHT_DOWN) ----> we dont need the mouse to report the MOVE event i suppose! qbutton = "Quit" position(10,10) puts(1,qbutton) while 1 do mouse = get_mouse() --if mouse != -1 then ----> error! --------------------------------------------------------------------- if sequence( mouse ) then -----> if not,mouse = -1 would cause error! -- if sequence( mouse ) then -- mouse press? clicked = and_bits( mouse[1], LEFT_DOWN ) ----->??????? -- some one knows the use of and_bits() in here???????? -- adjust mouse[2] = mouse[2]/8 --------> to scale the coordinates! mouse[3] = mouse[3]/8 --------> Thanks David Cuny,I missed -- this error!:) if mouse[2]>10 and mouse[2]<15 and mouse[3] = 10 then -->it should -- be the -- coordinates -- of the button puts(1,"quiting...") exit else position(1,1) puts(1,"you must hit Quit!") end if else -- no click clicked = 0 -- if mouse[3]>{10} then -- if mouse[2]<10+length(qbutton) then -- ^ --the [2] and [3] might need to be --switched on these two lines to work -- v -- if mouse[3]<10 then -- if find(LEFT_UP,mouse[1]) then -- run_quit_routine() --you get the idea? -- end if -- end if -- end if --end if end if mouse = {0,0,0} ---> to make sure that will be a sequence end while -- Thanks to David Cuny,Lewis Townsend and everybody! - Luis - >
7. Re: +Help!
- Posted by David Cuny <dcuny at DSS.CA.GOV> May 13, 1998
- 623 views
(I think) Luis Campos wrote: > -- mouse press? > clicked =3D and_bits( mouse[1], LEFT_DOWN ) ----->??????? > -- some one knows the use of and_bits() in here???????? The 'and_bits' is needed because there can be more than one mouse event = at a time. For example, the mouse could move AND the left button could = be clicked. The flags are ORd together. In this case, the returned = result would be: MOVE AND LEFT_DOWN which equals=20 1 AND 2 which is, of course, 3. In this case, the test: if mouse[1] =3D LEFT_DOWN would not detect the mouse click event, because 2 !=3D 3. If you look at = the flags, they are set up in powers of 2: global constant MOVE =3D 1, LEFT_DOWN =3D 2, LEFT_UP =3D 4, RIGHT_DOWN =3D 8 RIGHT_UP =3D 16, MIDDLE_DOWN =3D 32, MIDDLE_UP =3D 64 This is not by accident - you store all the flags into a single byte, by = setting the _bits_ in the flag: 1 =3D bit 0 =3D 2^0 2 =3D bit 1 =3D 2^1 4 =3D bit 2 =3D 2^2 8 =3D bit 3 =3D 2^3 16 =3D bit 4 =3D 2^4 32 =3D bit 5 =3D 2^5 64 =3D bit 6 =3D 2^6 To look at a _single_ bit in the byte, you AND the bits together. So the = test: if and_bits( mouse[1], LEFT_DOWN ) works because 3 AND 1 is equal to 1, and a non-zero result is treated as true. Note that 'and_bits' is different than 'and'; 'and' returns true if both = values are non-zero. It works like this: function and( object o1, object o2 ) if o1 then if o2 then return 1 end if end if return 0 end function So the test: -- WRONG! if mouse[1] and LEFT_DOWN then tests to see if both values are non-zero. It doesn't do actually do a = bit-by-bit comparison of the values. Hope this helps! -- David Cuny
8. Re: +Help!
- Posted by David Cuny <dcuny at LANSET.COM> May 13, 1998
- 604 views
- Last edited May 14, 1998
I had mistakenly written: >The flags are ORd together. In this case, the returned result would be: > > MOVE AND LEFT_DOWN > >which equals > > 1 AND 2 > >which is, of course, 3. I should have written: >The flags are ORd together. In this case, the returned result would be: > > MOVE OR LEFT_DOWN => or_bits( MOVE, LEFT_DOWN ) > >which equals > > 1 OR 2 => or_bits( 1, 2 ) > >which is, of course, 3. because 'and_bits( 1, 2 )' equals 0. Sorry about the typo. -- David Cuny
9. Re: +Help!
- Posted by Lewis Townsend <keroltarr at HOTMAIL.COM> May 14, 1998
- 609 views
Salutations, >Hi Lewis, > I tested your code and it doesn't works.There's a type-check failure > that i think that i've remove it changing 'mouse' to a object. > > Please,check out the following code! ;) I'll be surprised if a type-check failure was all that was wrong with my code. I used to call everything an object so that I wouldn't have to worry about types much but I've been trying to be more specific recently. Maybe it's better that way. (of course mouse needs to be an object) I guess debugging type check errors is easier than trying to figure out why your program is trying to subscript an atom (reading from it) ;) >-- Thanks to David Cuny,Lewis Townsend and everybody! I'm flattered that you actually used some of my code. I figured that some one else would have a much better solution. Sincerely, Lewis Townsend |\ ____ _ _ _ _ __ | \ | __/ || / | // || / __ \ | \ ||_ || //|| // || ||__\| | \ | _| || // || // || \___ \ | |\ \ ||__ ||// ||// || |\__|| | | \ \|___\ |_/ |_/ || \____/ | | \ \ _____ ________ | | \ \ | __ \ | __ __ | | | \ \ ||__|| |/ || \| | | \ \ | __ / || | |______\ \ || \\ || |___________\ || || || Keroltarr at hotmail.com ______________________________________________________ Get Your Private, Free Email at http://www.hotmail.com