/*----------------------------------------------------------------------------*/
/*                                                                            */
/* Copyright (c) 2006-2014 Rexx Language Association. All rights reserved.    */
/*                                                                            */
/* This program and the accompanying materials are made available under       */
/* the terms of the Common Public License v1.0 which accompanies this         */
/* distribution. A copy is also available at the following address:           */
/* https://www.oorexx.org/license.html                                        */
/*                                                                            */
/* Redistribution and use in source and binary forms, with or                 */
/* without modification, are permitted provided that the following            */
/* conditions are met:                                                        */
/*                                                                            */
/* Redistributions of source code must retain the above copyright             */
/* notice, this list of conditions and the following disclaimer.              */
/* Redistributions in binary form must reproduce the above copyright          */
/* notice, this list of conditions and the following disclaimer in            */
/* the documentation and/or other materials provided with the distribution.   */
/*                                                                            */
/* Neither the name of Rexx Language Association nor the names                */
/* of its contributors may be used to endorse or promote products             */
/* derived from this software without specific prior written permission.      */
/*                                                                            */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS        */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT          */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS          */
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT   */
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,      */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED   */
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,        */
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING    */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS         */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.               */
/*                                                                            */
/*----------------------------------------------------------------------------*/

/**
 *  DlgAreaDemoThree.Rex
 *
 *  Demonstrates a second approach to resizable dialogs.  Essentially what this
 *  approach does is to defer the redrawing of the dialog controls until the
 *  user has finished resizing the dialog.
 *
 *  This example is exactly like DlgAreaDemoTwo.rex, except it also demonstrates
 *  how to prevent the user from resizing the dialog smaller than a minimum
 *  size.  Look at the connectResizing() method in init() and the onResizing()
 *  method for the code that does this.
 *
 *  To better understand this example completely, please read the header
 *  comments in the DlgAreaDemoTwo.rex example.
 */

  sd = locate()
  .application~useGlobalConstDir("O", sd'dlgAreaUDemo.h')

  dlg = .ResizableDialog~new
  dlg~execute('ShowTop')

  return 0

::requires "ooDialog.cls"

::class 'ResizableDialog' subclass UserDialog

::method init

  forward class (super) continue
  success = self~createCenter(250, 250, 'My Flicker Free Resizable Dialog',     -
                                        'ThickFrame MinimizeBox MaximizeBox', , -
                                        'MS Sans Serif', 8)
  if \ success then do
    self~initCode = 1
    return
  end

  self~connectResize('onResize', .true)
  self~connectResizing('onResizing')
  self~connectSizeMoveEnded('onSizeMoveEnded')


::method defineDialog
  expose u sizing minMaximized

  u = .dlgAreaU~new(self)
  if u~lastError \= .nil then call errorDialog u~lastError

  -- Tell the DialogAreaU object to not invoke the update method.
  u~updateOnResize = .false

  -- We use these variables to track when to redraw, or not.
  sizing = .false
  minMaximized = .false

  u~noResizePut(IDC_PB_0)
  e = .dlgArea~new(u~x       , u~y       , u~w('70%'), u~h('90%'))   -- edit   area
  s = .dlgArea~new(u~x       , u~y('90%'), u~w('70%'), u~hr      )   -- status area
  b = .dlgArea~new(u~x('70%'), u~y       , u~wr      , u~hr      )   -- button area

  self~createEdit('IDC_EDIT', e~x, e~y, e~w, e~h, 'multiline')
  self~createStaticText('IDC_ST_STATUS', s~x, s~y, s~w, s~h, , 'Status info appears here')

  self~createPushButton('IDC_PB_0', b~x, b~y('00%'), b~w, b~h('9%'),          , 'Button' 0 , 'Button'||0)
  self~createPushButton('IDC_PB_1', b~x, b~y('10%'), b~w, b~h('9%'),          , 'Button' 1 , 'Button'||1)
  self~createPushButton('IDC_PB_2', b~x, b~y('20%'), b~w, b~h('9%'),          , 'Button' 2 , 'Button'||2)
  self~createPushButton('IDC_PB_3', b~x, b~y('30%'), b~w, b~h('9%'),          , 'Button' 3 , 'Button'||3)
  self~createPushButton('IDC_PB_4', b~x, b~y('40%'), b~w, b~h('9%'),          , 'Button' 4 , 'Button'||4)
  self~createPushButton('IDC_PB_5', b~x, b~y('50%'), b~w, b~h('9%'),          , 'Button' 5 , 'Button'||5)
  self~createPushButton('IDC_PB_6', b~x, b~y('60%'), b~w, b~h('9%'),          , 'Button' 6 , 'Button'||6)
  self~createPushButton('IDOK',     b~x, b~y('90%'), b~w, b~h('9%'), 'DEFAULT', 'Ok')


::method initDialog
  expose minWidth minHeight

  -- The underlying edit controls internally resize themselves as the dialog
  -- they are contained in is resized.  We don't want that, so we disable that
  -- behavior in the underlying edit control.
  self~newEdit(IDC_EDIT)~disableInternalResize

  -- We will restrict the minimum width and minimum height to our original
  -- width and height
  minWidth = self~pixelCX
  minHeight = self~pixelCY


-- The RESIZING event happens when the user is resizing the dialog, but *before*
-- the size of the dialog is actually changed.  The first arg is a .RECT object
-- that describes the new size.  If we change the coordinates in the rectangle,
-- and reply .true.  The new size of the dialog will be our changed coordinates.
--
-- Here, if the new size is smaller than we want, we just change the rectangle
-- coordinates to our minimum size.  The 'direction' argument tells us which
-- edge of the dialog the user is dragging.  We use that to decide which
-- coordinate(s) to change.
--
-- A maximum size for the dialog could be enforced in a similar way.
::method onResizing unguarded
  expose minWidth minHeight
  use arg r, direction

  select
    when direction == 'TOP' then do
      if r~bottom - r~top < minHeight then do
        r~top = r~bottom - minHeight
        return .true
      end
    end
    when direction == 'BOTTOM' then do
      if r~bottom - r~top < minHeight then do
        r~bottom = r~top + minHeight
        return .true
      end
    end
    when direction == 'LEFT' then do
      if r~right - r~left < minWidth then do
        r~left = r~right - minWidth
        return .true
      end
    end
    when direction == 'RIGHT' then do
      if r~right - r~left < minWidth then do
        r~right = r~left + minWidth
        return .true
      end
    end
    when direction == 'BOTTOMLEFT' then do
      didChange = .false

      if r~bottom - r~top < minHeight then do
        r~bottom = r~top + minHeight
        didChange = .true
      end

      if r~right - r~left < minWidth then do
        r~left = r~right - minWidth
        didChange = .true
      end

      return didChange
    end
    when direction == 'BOTTOMRIGHT' then do
      didChange = .false

      if r~bottom - r~top < minHeight then do
        r~bottom = r~top + minHeight
        didChange = .true
      end

      if r~right - r~left < minWidth then do
        r~right = r~left + minWidth
        didChange = .true
      end

      return didChange
    end
    when direction == 'TOPLEFT' then do
      didChange = .false

      if r~bottom - r~top < minHeight then do
        r~top = r~bottom - minHeight
        didChange = .true
      end

      if r~right - r~left < minWidth then do
        r~left = r~right - minWidth
        didChange = .true
      end

      return didChange
    end
    when direction == 'TOPRIGHT' then do
      didChange = .false

      if r~bottom - r~top < minHeight then do
        r~top = r~bottom - minHeight
        didChange = .true
      end

      if r~right - r~left < minWidth then do
        r~right = r~left + minWidth
        didChange = .true
      end

      return didChange
    end
    otherwise
      nop
  end
  -- End select
  return .false

::method onResize unguarded
  expose u sizing minMaximized lastSizeInfo
  use arg sizingType, sizeinfo

  -- Save the size information so we know the final size of the dialog.
  lastSizeInfo = sizeInfo

  -- The size / move ended event does not occur when the user maximizes,
  -- minimizes, or restores from maximized / minimized.  Because of that, we
  -- need to redraw the client area under those conditions.

  if sizingType == self~SIZE_MAXIMIZED | sizingType == self~SIZE_MINIMIZED then do
    minMaximized = .true
    if sizingType == self~SIZE_MAXIMIZED then do
      u~resize(self, sizeinfo)
      self~redrawClient(.true)
    end
  end
  else if sizingType == self~SIZE_RESTORED, minMaximized then do
    minMaximized = .false
    u~resize(self, sizeinfo)
    self~redrawClient(.true)
  end
  else do
    -- We are resizing now.
    sizing = .true
  end

  return 0


::method onSizeMoveEnded unguarded
  expose u sizing lastSizeInfo

  -- If we were resizing, force the dialog controls to redraw themselves.
  if sizing then do
    u~resize(self, lastSizeInfo)
    self~redrawClient(.true)
  end

  -- We are not resizing anymore.
  sizing = .false
  return 0


::method unknown
  use arg msgName, args

  if msgName~abbrev("BUTTON") then
    self~newStatic(IDC_ST_STATUS)~setText('You Pressed Button' msgName~right(1))
