############################################################################
#
# File  :   editor.icn
# Author:   Henrik Sandin
# Date  :   May 3, 1999
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
# This file contains procedures to handle user actions in the brick editor.
# An edited brick can be up to 10 x 10 sqares in size which is the width
# of the htetris playing field. A square is 20 by 20 pixels.
# A brick being edited is represented by a matrix, containing ones for
# colored squares and zeros for non-colored (black) squares.
# The editor is invoked and closed by the htetris module simply by changing
# the "canvas" attribute of the editor window.
#
############################################################################

############################################################################
#
# Global varibles used by both htetris.icn and editor.icn.
#
############################################################################

global editor_window    # The editor window, initially hidden.
global editor_vidgets   # The table of widgets in the editor interface.

############################################################################
#
# Global varibles used by editor.icn only.
#
# edit_pane  - The editing area, which is 200 by 200 pixels.
# grid_width - Current width of the grid (the active drawing area within
#              the edit pane).
# grid_height - Current height of the grid (the active drawing area within
#               the edit pane).
# grid_status        - Flag determining whether the grid is visible or not.
# mutable_grid_color - Mutable color of grid if mutable colors are used.
# mutable_brick_color       - Mutable base color of a brick.
# mutable_brick_color_light - Mutable light shade for 3D-effect on bricks.
# mutable_brick_color_dark  - Mutable dark shade for 3D-effect on bricks. 
# brick_color               - Color of brick on string format. 
# brick_matrix - Twodimensional matrix representing the current brick.
# mutables     - Flag determining whether mutable colors are used or not.
# saved    - Flag determining whether the current brick is saved or not.
#
############################################################################

global edit_pane
global mutable_grid_color   # Color of grid used if mutable colors are in use.
global grid_width
global grid_height
global grid_status          # Status of grid, 'ON' or 'OFF'.
global brick_color          # Current non-mutable color of brick.
global mutable_brick_color  # Color of brick used if mutable colors are in use.
global mutable_brick_color_light  
global mutable_brick_color_dark  
global brick_matrix         # The matrix representation of the current brick.
global mutables             # Flag indicating if mutable colors are used or not.
global saved                # Flag indicating if current brick is saved or not.

$define OFF       0    # Constant representing the grid state off.
$define ON        1    # Constant representing the grid state on.
$define NO        0    # Constant representing the semantics of no.
$define YES       1    # Constant representing the semantics of yes.
$define BLACK     0    # Constant representing a black square on the edit pane.
$define COLORED   1    # Constant representing a colored square.

############################################################################
#
# Procedure: start_editor
# Arguments: None.
# Returns  : Nothing.
#
# This procedure starts up the brick editor in a hidden window.
# The editing area is initialized and it is determined if mutable colors
# are to be used or not.
# On a slow machine, mutable colors might make the updating of the edit
# pane look better.
# Also, since no brick has been edited yet, 'saved' is set to 'YES'.
# This is only performed once when the htetris application is started.
#
############################################################################

procedure start_editor()

    atts := put( editor_atts(), "canvas=hidden")

    (editor_window := WOpen ! atts) | {
	Notice( htetris_window,
	        "Editor can not be used because",
	        "its window could not be opened.")
	fail
    }
	
    editor_vidgets := editor( editor_window)   
    pane_width     := editor_vidgets["edit"].uw
    pane_height    := editor_vidgets["edit"].uh
    edit_pane      := Clone( editor_window, "bg=black",
			     "dx=" || editor_vidgets["edit"].ux,
			     "dy=" || editor_vidgets["edit"].uy)

    Clip( edit_pane, 0, 0, pane_width, pane_height)
    EraseArea( edit_pane, 0, 0, pane_width, pane_height)

    mutable_brick_color       := NewColor()
    mutable_brick_color_light := NewColor()
    mutable_brick_color_dark  := NewColor()
    mutable_grid_color        := NewColor()

    if (mutable_brick_color       === &null  |
	mutable_brick_color_light === &null  |
	mutable_brick_color_dark  === &null  |
	mutable_grid_color        === &null) then
	mutables := NO
    else
	mutables := YES

    saved := YES
    return
end

############################################################################
#
# Procedure: kill_editor
# Arguments: None.
# Returns  : Nothing.
#
# This procedure closes down the editor, freeing mutable color if they are
# used and closing the editor window.
# This is only performed when the htetris application is closed.
#
############################################################################

procedure kill_editor()

    if mutables = YES then {
	FreeColor( mutable_brick_color)
	FreeColor( mutable_brick_color_light)
	FreeColor( mutable_brick_color_dark)
	FreeColor( mutable_grid_color)
    }
    WClose( editor_window)
    return
end

############################################################################
#
# Procedure: edit
# Arguments: None.
# Returns  : Nothing.
#
# This is the event loop for the editor which is entered by the htetris
# application when the editor is to be used.
#
############################################################################

procedure edit()

    while (*Pending( editor_window) > 0) do
	ProcessEvent( root)
    
    return
end

############################################################################
#
# Procedure: reset_editor
# Arguments: matrix    - A matrix representing a new brick (possibly empty).
#            new_color - New color.
# Returns  : Nothing.
#
# This procedure resets the editor using the matrix and the given color.
# The edit pane is cleared and the grid is shown.
#
############################################################################

procedure reset_editor( matrix, new_color)

    grid_width   := *matrix[1]   # Number of columns.
    grid_height  := *matrix      # Number of rows.
    brick_color  := new_color
    brick_matrix := matrix

    if mutables = YES then {
	Color( mutable_brick_color, new_color)
	Color( mutable_brick_color_light, "light-" || new_color)
	Color( mutable_brick_color_dark, "dark-" || new_color)
	Color( mutable_grid_color, "white")
    }

    EraseArea( edit_pane, 0, 0,
	       editor_vidgets["edit"].uw, editor_vidgets["edit"].uh)

    if mutables = YES then
	draw_grid( mutable_grid_color)
    else
	draw_grid( "white")

    grid_status := ON
    return
end

############################################################################
#
# Procedure: draw_brick
# Arguments: window - The window in which to draw the brick.
#            color  - Color in which to draw the brick.
#            matrix - The matrix representation of the brick.
# Returns  : Nothing.
#
# This procedure draws a brick in a specified window using the specified
# color andbrick matrix.
# For every colored element in the matrix a square is drawn in the given
# color if mutable colors aren't used. Otherwise the current mutable brick
# color is used.
#
############################################################################

procedure draw_brick( window, color, matrix)

    every r := 1 to *matrix do
	every c := 1 to *matrix[r] do
	    if matrix[r][c] = COLORED then
		if mutables = YES then
		    draw_mutable_square( r, c, window)
		else
		    draw_square( r, c, window, color)
    return
end

############################################################################
#
# Procedure: draw_grid
# Arguments: color - Grid color.
# Returns  : Nothing.
#
# This procedure redraws the grid in in all non-colored squares in the
# specified grid color which is either white, black or the mutable grid-
# color.
#
############################################################################

procedure draw_grid( color)

    Fg( edit_pane, color)
    every r := 1 to grid_height do
	every c := 1 to grid_width do
	    if brick_matrix[r][c] = BLACK then
		DrawSegment( edit_pane,
			     (c-1)*20, (r-1)*20, (c-1)*20, (r-1)*20+19,
			     (c-1)*20, (r-1)*20, (c-1)*20+19, (r-1)*20)

    DrawSegment( edit_pane, 0, grid_height*20, grid_width*20, grid_height*20,
		            grid_width*20, 0, grid_width*20, grid_height*20)
    return
end

############################################################################
#
# Procedure: remove_grid
# Arguments: None.
# Returns  : Nothing.
#
# This procedure removes the grid from the edit pane by setting its
# color where it is shown to black, either by changing the mutable color
# or calling draw_grid.
#
############################################################################

procedure remove_grid()

    if mutables = YES then
	Color( mutable_grid_color, "black")
    else
	draw_grid( "black")
    return
end

############################################################################
#
# Procedure: apply_grid
# Arguments: None.
# Returns  : Nothing.
#
# This procedure shows the grid on the edit pane by setting its
# color where it is shown to white, either by changing the mutable color
# or calling draw_grid.
#
############################################################################

procedure apply_grid()

    if mutables = YES then
	Color( mutable_grid_color, "white")
    else
	draw_grid( "white")
    return
end

############################################################################
#
# Procedure: ctop
# Arguments: coordinate - An x or y coordinate in the pixel coordinate system.
# Returns  : The corresponding row or column position on the edit pane.
#
# This procedure converts an x or y pixel coordinate on the edit pane to
# the corresponding row or column number.
# Row and column numbers starts at 1 and are 20 pixels in height and width
# respectively.
#
############################################################################

procedure ctop( coordinate)

    while coordinate % 20 ~= 0 do coordinate := coordinate-1

    return coordinate/20+1
end

############################################################################
#
# Procedure: invalid
# Arguments: color - A color on string format.
# Returns  : Succseeds if the color is not a valid brick color, fails
#            otherwise.
#
# This procedure determines whether the given color is invalid as a brick
# color.
#
############################################################################

procedure invalid( color)

    valid_colors := set(["yellow", "red", "blue", "green", "orange",
			 "magenta", "cyan", "brown"])

    return not member( valid_colors, color)
end

############################################################################
#
# Procedure: out_of_bounds
# Arguments: width  - An integer width.
#            height - An integer height.
# Returns  : Succseeds if width and height are not between 1 and 10 inclusive,
#            fails otherwise.
#
# This procedure determines whether the given width and height are invalid
# brick measurements. A brick must be between 1 x 1 and 10 x 10 squares.
#
############################################################################

procedure out_of_bounds( width, height)

    return width > 10 | width < 1 | height > 10 | height < 1
end

############################################################################
#
# Procedure: edit_new
# Arguments: None.
# Returns  : Nothing.
#
# This procedure shows a text dialog box with buttons "Ok" and "Cancel",
# where the user is asked to enter width, height and color of a new brick.
# The three input values are checked for validity and if they are correct,
# the editor is reset with the new values and 'saved' is set to 'YES'.
# If they are not correct, an error message is given and the dialog
# reappears until the user enters valid values or cancel is pressed.
#
############################################################################

procedure edit_new()

    button_pressed :=
	TextDialog( editor_window,
		   ["Enter properties of the brick."],
		   ["Width:", "Height:", "Color:"],
		   [],
		   [2, 2, 20])
    
    case button_pressed of {
	"Okay" : {
	    width  := integer( dialog_value[1])
	    height := integer( dialog_value[2])
	    color  := dialog_value[3]
	    
	    if (width === &null | height === &null) |
	       (out_of_bounds( width, height))      then {
		Notice( editor_window,
		        "Width and height must be between 1 and 10.")
		edit_new()
		return
	    }
	    else if invalid( color) then {
		Notice( editor_window,
		       "Color must be one of the following:",
		       "yellow, red, blue, green, orange,",
		       "magenta, cyan or brown.")
		edit_new()
		return
	    }
	    else {
		reset_editor( new_matrix( height, width), color)
		saved := YES
	    }
	}
    }
    return
end

############################################################################
#
# Procedure: edit_open
# Arguments: None.
# Returns  : Nothing.
#
# Brick data are obtained by a call to 'open_brick'.
# If they were successfully returned, appropriate elements of them are
# extracted to reset the editor according to the attributes of the
# loaded brick and draw it on the edit pane. 'saved' is set to 'YES'.
#
############################################################################

procedure edit_open()
    
    old_pointer := WAttrib( editor_window, "pointer")
    if old_pointer == "left ptr" then
	WAttrib( editor_window, "pointer=watch")
    else
	WAttrib( editor_window, "pointer=wait")
	
    if /(brick_data := open_brick( editor_window)) then
	return

    reset_editor( brick_data.matrices[1], brick_data.color)
    draw_brick( edit_pane, brick_color, brick_matrix)    
    WAttrib( editor_window, "pointer=" || old_pointer)
    saved := YES
    return
end

############################################################################
#
# Procedure: empty_pane
# Arguments: None.
# Returns  : One of the constants YES or NO.
#
# This procedure determines if the edit pane is empty by traversing the
# grid matrix. 'YES' is returned if all elements in the matrix were black.
# If at least one element is colored, 'NO' is returned.
#
############################################################################

procedure empty_pane()

    every r := 1 to grid_height do
	every c := 1 to grid_width do
	    if brick_matrix[r][c] ~= BLACK then
		return NO
    return YES
end

############################################################################
#
# Procedure: save_temp_window
# Arguments: width       - Width of the temporary window.
#            height      - Height of the temporary window.
# Returns  : temp_window - The temporary window.
#
# This procedure opens and returns a temporary hidden window of the given
# size. This is used to draw a brick temporarily when saving it.
#
############################################################################

procedure save_temp_window( width, height)

    temp_window :=
	WOpen( "width=" || width,
	       "height=" || height,
	       "bg=black",
	       "canvas=hidden") | {
	    Notice( editor_window, "Error while saving brick, save aborted.")
	    return
	}
    return temp_window
end

############################################################################
#
# Procedure: transparentify
# Arguments: spec - An icon imagestring specification.
# Returns  : temp - The transformed specification.
#
# This procedure transforms and returns an imagestring with colors from
# the "c1" palette to a transparent imagestring, replacing all black pixels
# (zeros) with transparent pixels (~).
#
############################################################################

procedure transparentify( spec)
    spec ? {
	temp := tab( upto( ',')) || move( 1) ||
	        tab( upto( ',')) || move( 1)

	while colored := tab( upto( '0')) do {
	    nr_black := many( '0') - &pos
	    tab( many( '0'))
	    transparent := repl( "~", nr_black)
	    temp := temp || colored || transparent
	}
	if temp := temp || move( 1) then
	    temp := temp || tab( many( cset( PaletteChars( "c1")) -- '0'))
    }
    return temp
end

############################################################################
#
# Procedure: assemble_data
# Arguments: None.
# Returns  : A 'brick' record containing data of the current brick.
#
# This procedure assembles data for the current brick, which includes the
# color, four matrices and four corresponding image-strings.
# The first brick matrix must first be trimmed if all of the availible area
# on the edit pane has not been used.
# The trimmed brick matrix is then rotated and drawn in temporary windows
# which contents are captured as imagestrings. Each of the four image-
# strings produced are converted to transparent ones where all black pixels
# become transparent instead.
# A record of type 'brick' is returned with all fields but 'offset'
# filled in.
#
############################################################################

procedure assemble_data( wait_window)

    area_used := non_zero_limits( brick_matrix)
    work_done( wait_window, 10)

    x      := (area_used.min_col-1)*20
    y      := (area_used.min_row-1)*20
    width  := (area_used.max_col-area_used.min_col+1)*20
    height := (area_used.max_row-area_used.min_row+1)*20
    work_done( wait_window, 12)

    if /(temp_window1 := save_temp_window( height, width)) then fail
    if /(temp_window2 := save_temp_window( width, height)) then fail
    if /(temp_window3 := save_temp_window( height, width)) then fail
    work_done( wait_window, 15)
    
    if grid_status = ON then remove_grid()
    image1 := transparentify( Capture( edit_pane, "c1", x, y, width, height))
    if grid_status = ON then apply_grid()
    work_done( wait_window, 30)
    
    matrix1 := trim_matrix( brick_matrix)
    work_done( wait_window, 40)
    
    if mutables = YES then
	color := mutable_brick_color
    else
	color := brick_color
    work_done( wait_window, 42)

    draw_brick( temp_window1, color, matrix2 := rotate_matrix( matrix1))
    image2 := transparentify( Capture( temp_window1, "c1", 0, 0, height, width))
    work_done( wait_window, 58)
    
    draw_brick( temp_window2, color, matrix3 := rotate_matrix( matrix2))
    image3 := transparentify( Capture( temp_window2, "c1", 0, 0, width, height))
    work_done( wait_window, 74)
    
    draw_brick( temp_window3, color, matrix4 := rotate_matrix( matrix3))
    image4 := transparentify( Capture( temp_window3, "c1", 0, 0, height, width))
    work_done( wait_window, 90)

    WClose( temp_window1)
    WClose( temp_window2)
    WClose( temp_window3)
    work_done( wait_window, 95)

    return brick( brick_color,
		  &null,
		  [matrix1, matrix2, matrix3, matrix4],
		  [image1, image2, image3, image4])
end

############################################################################
#
# Procedure: edit_save
# Arguments: None.
# Returns  : Nothing.
#
# This procedure saves the current brick to disk, first checking if the
# edit pane is empty.
#
############################################################################

procedure edit_save()

    if empty_pane() = YES then
	Notice( editor_window, "Edit pane is empty, save aborted.")
    else {
	save_brick( editor_window)
	saved := YES
    }
    return
end

############################################################################
#
# Procedure: change_color
# Arguments: None.
# Returns  : Nothing.
#
# This procedure shows a text dialog box with buttons "Ok" and "Cancel",
# asking the user to enter a new brick color.
# If the entered color is invalid, the dialog reappears until a valid
# color is entered or cancel is pressed.
# If the color was valid, the global variable 'brick_color' is updated and
# the squares currently colored on the edit pane are updated to the new
# color.
#
############################################################################

procedure change_color()

    button_pressed :=
	TextDialog( editor_window,
		   ["Enter new color."],
		   ["Color:"],
		   [],
		   [20])

    case button_pressed of {
	"Okay" : {
	    if invalid( dialog_value[1]) then {
		Notice( editor_window,
		       "Color must be one of the following:",
		       "yellow, red, blue, green, orange,",
		       "magenta, cyan or brown.")
		change_color()
		return
	    }
	    else {
		brick_color := dialog_value[1]
		if mutables = YES then {
		    Color( mutable_brick_color, brick_color)
		    Color( mutable_brick_color_light, "light-" || brick_color)
		    Color( mutable_brick_color_dark, "dark-" || brick_color)
		}
		else
		    draw_brick( edit_pane, brick_color, brick_matrix)
	    }
	}
    }
    return
end

############################################################################
#
# Procedure: draw_mutable_square
# Arguments: r      - Row number of square to be drawn.
#            c      - Column number of square to be drawn.
#            window - Window in which the square is to be drawn.
# Returns  : Nothing.
#
# This procedure draws a square using the current mutable color in the
# given window.
# A lighter and a darker shade of the base color is used to create a
# 3 dimensional effect.
#
############################################################################

procedure draw_mutable_square( r, c, window)

    Fg( window, mutable_brick_color)
    FillRectangle( window, (c-1)*20, (r-1)*20, 20, 20)
    Fg( window, mutable_brick_color_light)
    DrawLine( window, (c-1)*20, (r-1)*20, (c*20)-1, (r-1)*20)
    DrawLine( window, (c-1)*20, (r-1)*20+1, (c*20)-1, (r-1)*20+1)
    DrawLine( window, (c-1)*20, (r-1)*20, (c-1)*20, (r*20)-1)
    DrawLine( window, (c-1)*20+1, (r-1)*20, (c-1)*20+1, (r*20)-2)
    Fg( window, mutable_brick_color_dark)
    DrawLine( window, (c*20)-1, (r*20)-1, (c*20)-1, (r-1)*20+1)
    DrawLine( window, (c*20)-2, (r*20)-1, (c*20)-2, (r-1)*20+2)
    DrawLine( window, (c*20)-1, (r*20)-1, (c-1)*20+1, (r*20)-1)
    DrawLine( window, (c*20)-1, (r*20)-2, (c-1)*20+2, (r*20)-2)
    return
end

############################################################################
#
# Procedure: draw_square
# Arguments: r      - Row number of square to be drawn.
#            c      - Column number of square to be drawn.
#            window - Window in which the square is to be drawn.
#            color  - Color of square.
# Returns  : Nothing.
#
# This procedure draws a square using the given color in the given window.
# A lighter and a darker shade of the base color is used to create a
# 3 dimensional effect.
#
############################################################################

procedure draw_square( r, c, window, color)

    Fg( window, color)
    FillRectangle( window, (c-1)*20, (r-1)*20, 20, 20)
    Fg( window, "light-" || color)
    DrawLine( window, (c-1)*20, (r-1)*20, (c*20)-1, (r-1)*20)
    DrawLine( window, (c-1)*20, (r-1)*20+1, (c*20)-1, (r-1)*20+1)
    DrawLine( window, (c-1)*20, (r-1)*20, (c-1)*20, (r*20)-1)
    DrawLine( window, (c-1)*20+1, (r-1)*20, (c-1)*20+1, (r*20)-2)
    Fg( window, "dark-" || color)
    DrawLine( window, (c*20)-1, (r*20)-1, (c*20)-1, (r-1)*20+1)
    DrawLine( window, (c*20)-2, (r*20)-1, (c*20)-2, (r-1)*20+2)
    DrawLine( window, (c*20)-1, (r*20)-1, (c-1)*20+1, (r*20)-1)
    DrawLine( window, (c*20)-1, (r*20)-2, (c-1)*20+2, (r*20)-2)
    return
end

############################################################################
#
# Procedure: erase_square
# Arguments: r - Row number of square to be erased.
#            c - Column number of square to be erased.
# Returns  : Nothing.
#
# This procedure is called when a square on the edit pane is to be erased
# due to a right button mouse-click event on it.
# The matrix of the current brick is updated, the appropriate foreground
# color for the grid is selected depending on if mutable colors are in use
# or not and the square is erased and the grid in that square is redrawn.
#
############################################################################

procedure erase_square( r, c)

    if mutables = YES then
	Fg( edit_pane, mutable_grid_color)    
    else
	Fg( edit_pane, "white")
    
    EraseArea( edit_pane, (c-1)*20, (r-1)*20, 20, 20)
    if grid_status = ON then
	DrawSegment( edit_pane,
		     (c-1)*20, (r-1)*20, (c-1)*20, (r-1)*20+19,
		     (c-1)*20, (r-1)*20, (c-1)*20+19, (r-1)*20)
    return
end

################################ CALLBACKS #################################

############################################################################
#
# Procedure: edit_cb
# Arguments: vidget - Edit pane region.
#            event  - Event on the edit pane region.
#            x      - Mouse x-coordinate.
#            y      - Mouse y-coordinate.
# Returns  : Nothing.
#
# This procedure is called if an event has occured on the edit pane region.
# Only left and right mouse-button press events are handled.
# The x and y coordinate are transformed into row and column numbers and
# checked if they are whithin the current brick size area (the area covered
# by the grid) on the edit pane. If not nothing happens.
# If they are valid, a square is colored as an effect of a left button
# press, and erased as an effect of a right button press.
# In either case, the current brick matrix is updated accordingly.
# 'saved' is set to 'NO' since the current brick has now changed.
#
############################################################################

procedure edit_cb( vidget, event, x, y)

    x := x-WAttrib( edit_pane, "dx")-1
    y := y-WAttrib( edit_pane, "dy")-1
    r := ctop( y)
    c := ctop( x)
    
    if (r <= grid_height & c <= grid_width) then {
	case event of {
	    &lpress : {
		brick_matrix[r][c] := COLORED
		if mutables = YES then
		    draw_mutable_square( r, c, edit_pane)
		else
		    draw_square( r, c, edit_pane, brick_color)
	    }
	    &rpress : {
		brick_matrix[r][c] := BLACK
		erase_square( r, c)
	    }
	}
	saved := NO
    }
    return
end

############################################################################
#
# Procedure: editor_help_cb
# Arguments: vidget - Vidget id.
#            value  - A list, the menu item selected.
# Returns  : Nothing.
#
# This procedure is called when a menu item on the help menu of the editor
# is selected.
#
############################################################################

procedure editor_help_cb( vidget, value)

    case value[1] of {
	"How to edit" : how_to_edit()
	"Menus"       : file_menu()
    }
    return
end

############################################################################
#
# Procedure: file_cb
# Arguments: vidget - Vidget id.
#            value  - A list, the menu item selected.
# Returns  : Nothing.
#
# This procedure is called when a menu item on the file menu of the editor
# is selected.
# If "New" was selected, a new brick dialog is shown, possibly prompting to
# save the current brick first.
# If "Open" was selected, an open brick dialog is shown, possibly prompting
# to save the current brick first.
# If "Save" was selected, a save brick dialog is shown.
# If "Quit" was selected, possibly prompting to save the current brick
# first, saved is unconditionally set to "YES" since when the editor is
# run the next time it is to be "brand new". Then, the stream of events
# are switched over to the htetris window which pending events are discarded.
# Then the editor window is hidden.
#
############################################################################

procedure file_cb( vidget, value)

    case value[1] of {
	"New"  : {
	    if saved = NO then save_prompt( editor_window)
	    edit_new()
	}
	"Open" : {
	    if saved = NO then save_prompt( editor_window)
	    edit_open()
	}
	"Save" : edit_save()
	"Quit" : {
	    if saved = NO then save_prompt( editor_window)
	    saved := YES
	    root  := htetris_vidgets["root"]
	    while get( Pending( htetris_window))
	    WAttrib( editor_window, "canvas=hidden")
	}
    }
    return
end

############################################################################
#
# Procedure: brick_cb
# Arguments: vidget - Vidget id.
#            value  - A list, the menu item selected.
# Returns  : Nothing.
#
# This procedure is called when a menu item on the brick menu of the editor
# is selected.
# The only item is "Change color" so the color of the current brick is
# changed.
#
############################################################################

procedure brick_cb( vidget, value)

    case value[1] of {
	"Change color" : change_color()
    }
    return
end

############################################################################
#
# Procedure: clear_cb
# Arguments: vidget - Vidget id.
#            value  - A list, the menu item selected.
# Returns  : Nothing.
#
# This procedure is called when the button with the label "Clear" has been
# pressed.
# The brick matrix is reset by creating a new one of the same size.
# Then the whole edit pane is erased and if the grid was previously shown,
# it is redrawn in the appropriate foreground color.
#
############################################################################

procedure clear_cb( vidget, value)

    brick_matrix := new_matrix( grid_height, grid_width)

    EraseArea( edit_pane, 0, 0,
	       editor_vidgets["edit"].uw, editor_vidgets["edit"].uh)

    if grid_status = ON then
	if mutables = YES then
	    draw_grid( mutable_grid_color)
	else
	    draw_grid( "white")
    else
	if mutables = YES then
	    draw_grid( mutable_grid_color)
	else	
	    draw_grid( "black")
    return
end

############################################################################
#
# Procedure: toggle_cb
# Arguments: vidget - Vidget id.
#            value  - A list, the menu item selected.
# Returns  : Nothing.
#
# This procedure is called when the button with the label "Toggle grid" has
# been pressed.
# The grid is toggled by calling the appropriate procedure and update the
# global variable 'grid_status' accordingly depending on whether the grid
# is currently shown or not.
#
############################################################################

procedure toggle_cb( vidget, value)

    if grid_status == ON then {
	remove_grid()
	grid_status := OFF
    }
    else {
	apply_grid()
	grid_status := ON
    }
    return
end

#===<<vib:begin>>===	modify using vib; do not remove this marker line
procedure editor_atts()
   return ["size=216,276", "bg=gray-white", "label=Brick editor"]
end

procedure editor(win, cbk)
return vsetup(win, cbk,
   ["editor:Sizer:::0,0,216,276:Brick editor",],
   ["brick:Menu:pull::36,0,43,21:Brick",brick_cb,
      ["Change color"]],
   ["clear:Button:regular::6,240,90,30:Clear",clear_cb],
   ["editor_help:Menu:pull::79,0,36,21:Help",editor_help_cb,
      ["How to edit","Menus"]],
   ["editor_menubar:Line:::0,22,212,22:",],
   ["file:Menu:pull::0,0,36,21:File",file_cb,
      ["New","Open","Save","Quit"]],
   ["toggle:Button:regular::119,240,90,30:Toggle grid",toggle_cb],
   ["edit:Rect:raised::6,30,204,204:",edit_cb],
   )
end
#===<<vib:end>>===	end of section maintained by vib
