/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup DNA
 */

#pragma once

#include "BLI_enum_flags.hh"

#include "DNA_vec_types.h"

namespace blender {

namespace ui {
struct SmoothView2DStore;
}

/** View zooming restrictions, per axis (#View2D.keepzoom) */
enum eView2D_KeepZoom : short {
  /* zoom is clamped to lie within limits set by minzoom and maxzoom */
  V2D_LIMITZOOM = (1 << 0),
  /* aspect ratio is maintained on view resize */
  V2D_KEEPASPECT = (1 << 1),
  /* zoom is kept when the window resizes */
  V2D_KEEPZOOM = (1 << 2),
  /* zooming on x-axis is not allowed */
  V2D_LOCKZOOM_X = (1 << 8),
  /* zooming on y-axis is not allowed */
  V2D_LOCKZOOM_Y = (1 << 9),
};
ENUM_OPERATORS(eView2D_KeepZoom)

/** View panning restrictions, per axis (#View2D.keepofs). */
enum eView2D_KeepOfs : short {
  /* panning on x-axis is not allowed */
  V2D_LOCKOFS_X = (1 << 1),
  /* panning on y-axis is not allowed */
  V2D_LOCKOFS_Y = (1 << 2),
  /* on resize, keep the x offset */
  V2D_KEEPOFS_X = (1 << 3),
  /* on resize, keep the y offset */
  V2D_KEEPOFS_Y = (1 << 4),
};
ENUM_OPERATORS(eView2D_KeepOfs)

/** View extent restrictions (#View2D.keeptot). */
enum eView2D_KeepTot : short {
  /** 'cur' view can be out of extents of 'tot' */
  V2D_KEEPTOT_FREE = 0,
  /** 'cur' rect is adjusted so that it satisfies the extents of 'tot', with some compromises */
  V2D_KEEPTOT_BOUNDS = 1,
  /** 'cur' rect is moved so that the 'minimum' bounds of the 'tot' rect are always respected
   * (particularly in x-axis) */
  V2D_KEEPTOT_STRICT = 2,
};

/** General refresh settings (#View2D.flag). */
enum eView2D_Flag : short {
  /* global view2d horizontal locking (for showing same time interval) */
  V2D_VIEWSYNC_SCREEN_TIME = (1 << 0),
  /* within area (i.e. between regions) view2d vertical locking */
  V2D_VIEWSYNC_AREA_VERTICAL = (1 << 1),
  /* apply pixel offsets on x-axis when setting view matrices */
  V2D_PIXELOFS_X = (1 << 2),
  /* apply pixel offsets on y-axis when setting view matrices */
  V2D_PIXELOFS_Y = (1 << 3),
  /* zoom, pan or similar action is in progress */
  V2D_IS_NAVIGATING = (1 << 9),
  /* view settings need to be set still... */
  V2D_IS_INIT = (1 << 10),
  /* Ensure scrolling always snaps to multiples of #View2D.page_size_y or the #View2D.mask height
   * if this is 0. Zooming doesn't respect this. */
  V2D_SNAP_TO_PAGESIZE_Y = (1 << 11),
  /* Ignore keepofs flags only during zoom.
   * Allows for different behavior between zooming and area resize. */
  V2D_ZOOM_IGNORE_KEEPOFS = (1 << 12),
};
ENUM_OPERATORS(eView2D_Flag)

/** Scroller flags for View2D (#View2D.scroll). */
enum eView2D_Scroll : short {
  /* Left scroll-bar. */
  V2D_SCROLL_LEFT = (1 << 0),
  V2D_SCROLL_RIGHT = (1 << 1),
  V2D_SCROLL_VERTICAL = (V2D_SCROLL_LEFT | V2D_SCROLL_RIGHT),
  /* Horizontal scroll-bar. */
  V2D_SCROLL_TOP = (1 << 2),
  V2D_SCROLL_BOTTOM = (1 << 3),
  /* UNUSED                    = (1 << 4), */
  V2D_SCROLL_HORIZONTAL = (V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM),
  /* display vertical scale handles */
  V2D_SCROLL_VERTICAL_HANDLES = (1 << 5),
  /* display horizontal scale handles */
  V2D_SCROLL_HORIZONTAL_HANDLES = (1 << 6),
  /* Induce hiding of scroll-bar - set by region drawing in response to size of region. */
  V2D_SCROLL_VERTICAL_HIDE = (1 << 7),
  V2D_SCROLL_HORIZONTAL_HIDE = (1 << 8),
  /* Scroll-bar extends beyond its available window -
   * set when calculating scroll-bar for drawing */
  V2D_SCROLL_VERTICAL_FULLR = (1 << 9),
  V2D_SCROLL_HORIZONTAL_FULLR = (1 << 10),
};
ENUM_OPERATORS(eView2D_Scroll)

/** scroll_ui, activate flag for drawing. */
enum eView2D_ScrollUI : short {
  V2D_SCROLL_H_ACTIVE = (1 << 0),
  V2D_SCROLL_V_ACTIVE = (1 << 1),
};
ENUM_OPERATORS(eView2D_ScrollUI)

/**
 * Alignment flags for `totrect`, flags use 'shading-out' convention (#View2D.align).
 */
enum eView2D_Align : short {
  /* all quadrants free */
  V2D_ALIGN_FREE = 0,
  /* horizontal restrictions */
  V2D_ALIGN_NO_POS_X = (1 << 0),
  V2D_ALIGN_NO_NEG_X = (1 << 1),
  /* vertical restrictions */
  V2D_ALIGN_NO_POS_Y = (1 << 2),
  V2D_ALIGN_NO_NEG_Y = (1 << 3),
};
ENUM_OPERATORS(eView2D_Align)

/* ---------------------------------- */

/** View 2D data - stored per region. */
struct View2D {
  /** Total area that data can be drawn in. */
  rctf tot = {};
  /** Current region of tot that is visible in viewport. */
  rctf cur = {};
  /** Vertical scroll-bar region. */
  rcti vert = {};
  /** Horizontal scroll-bar region. */
  rcti hor = {};
  /**
   * Mask region (in screen-space) within which `cur` can be viewed.
   *
   * Note that the coordinates are inclusive; to get pixel size you need to use
   * `BLI_rcti_size_x(mask) + 1` (same for the Y axis).
   */
  rcti mask = {};

  /** Min/max sizes of `cur` rect (only when keepzoom not set). */
  float min[2] = {}, max[2] = {};
  /** Allowable zoom factor range (only when (keepzoom & V2D_LIMITZOOM)) is set. */
  float minzoom = 0, maxzoom = 0;

  /** Scroll-bars to display (bit-flag). */
  eView2D_Scroll scroll = {};
  /** Temporary settings used for UI drawing of scroll-bars. */
  eView2D_ScrollUI scroll_ui = {};

  /** Keeptot - `cur` rect cannot move outside the `tot` rect? */
  eView2D_KeepTot keeptot = {};
  /** Keepzoom - axes that zooming cannot occur on, and also clamp within zoom-limits. */
  eView2D_KeepZoom keepzoom = {};
  /** Keepofs - axes that translation is not allowed to occur on. */
  eView2D_KeepOfs keepofs = {};

  /** Settings. */
  eView2D_Flag flag = {};
  /** Alignment of content in totrect. */
  eView2D_Align align = {};

  /** Storage of current winx/winy values, set in view2d_size_update. */
  short winx = 0, winy = 0;
  /**
   * Storage of previous winx/winy values encountered by #view2d_curRect_validate(),
   * for V2D_KEEPZOOM and V2D_KEEPASPECT.
   */
  short oldwinx = 0, oldwiny = 0;

  /** Pivot point for transforms (rotate and scale). */
  short around = 0;

  /* Usually set externally (as in, not in view2d files). */
  /** Alpha of vertical and horizontal scroll-bars (range is [0, 255]). */
  char alpha_vert = 0, alpha_hor = 0;

  char _pad[2] = {};
  /**
   * When set (not 0), determines how many pixels to scroll when scrolling an entire page.
   * Otherwise the height of #View2D.mask is used.
   */
  float page_size_y = 0;

  /* animated smooth view */
  ui::SmoothView2DStore *sms = nullptr;
  struct wmTimer *smooth_timer = nullptr;
};

}  // namespace blender
