
// SPDX-License-Identifier: CC-BY-NC-SA-4.0
//
// Copyright (C) 2026 Bit by Bit Signal Processing LLC (https://bxbsp.com)
//
// This work is placed under the "Creative Commons Attribution
// NonCommercial ShareAlike 4.0 International" license, known
// by the shortened acronym "CC-BY-NC-SA-4.0".
//
// This work is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// A CC-BY-NC-SA-4.0 license allows you to use this work for
// noncommercial purposes so long as attribution is made to the
// original author.  Modified versions of this work may be distributed,
// but only under the same license.  For further details, see the
// Creative Commons License "CC-BY-NC-SA-4.0".
//
// You should have received a copy of the CC-BY-NC-SA-4.0 license
// along with this work. If not, see
// <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
//
//


#ifndef WINDOW_HH
#define WINDOW_HH

#include "panel.hh"
#include "subpanel.hh"
#include "color.hh"
#include "point.hh"
#include "backing_panel.hh"
#include "event_listener.hh"

//
// Windows have the concept of being redrawn statically, with a dynamic overlay.  This
// is for efficiency, that all doesn't need to be redrawn on every frame.  Instead,
// the static items are drawn once at layout and not redrawn unless a new layout is
// required.  This draw is saved in the display's static copy.  The display can then be
// redrawn directly from the static copy.  When something static changes in a window,
// the window is marked dirty if the change doesn't require a full redraw, or layout_dirty
// if a full redraw is required.  dirty usually means redraw of a child window for
// a multiwindow.
//
// Things are marked dirty rather than immediately redrawing them since there may be
// many things that change in a single event, and we only want to redraw once
// even though many changes may require a redraw.
//
//
// draw_dynamic:                            Draw dynamic stuff into parent's panel, typically over previously
//                                          drawn static stuff.
//
// layout:                                  Recalculate basic underlying parameters and full redraw.
//
//
// draw_dirty:                              Redraw items that might have flagged a redraw but not a full
//                                          redraw.  The typical case is children of a multiwindow.
//

class window : public panel, public event_listener
{
public:
  class multiwindow*      parent;
  point                   offset;

  color                   bgcolor;

  bool                    window_subject_to_layout;

  bool                    layout_dirty;   // Needs to be layout out again and then redrawn.  All children also.
  bool                    dirty;          // Needs to be redrawn.  Some children may also need to be layed out.

  // resize() is alled from events or from layout().  If called from layout,
  // layout() must be called on the resized item afterwards.
  virtual void            resize                     (int x, int y, int w, int h);
  virtual void            resize_quietly             (int x, int y, int w, int h);

  // Called from events.
  virtual void            mark_dirty                 ();
  virtual void            mark_layout_dirty          ();


  // Called from vertical blank redraw.  To be overridden by derived classes.  Called in the order below, as needed.
  virtual void            layout                     ();  // recalculates geometry, does full redraw
  virtual void            draw_dirty                 ();  // redraws only children marked dirty
  virtual void            draw_dynamic               ();

  // Utility drawing functions
  virtual void            draw_point_no_boundscheck  (point p, color c);
  virtual color           get_point_no_boundscheck   (point p);

  virtual void            draw_text(const char*     text, color c, int x, int y, int flags = 0);
  virtual void            draw_text(const wchar_t*  text, color c, int x, int y, int flags = 0);
  virtual void            draw_text(const char16_t* text, color c, int x, int y, int flags = 0);
  virtual void            draw_text(const char32_t* text, color c, int x, int y, int flags = 0);

  virtual void            draw_multicolored_text(const char*     text, int start_color, dt_colors& c, int x, int y, int flags = 0);
  virtual void            draw_multicolored_text(const wchar_t*  text, int start_color, dt_colors& c, int x, int y, int flags = 0);
  virtual void            draw_multicolored_text(const char16_t* text, int start_color, dt_colors& c, int x, int y, int flags = 0);
  virtual void            draw_multicolored_text(const char32_t* text, int start_color, dt_colors& c, int x, int y, int flags = 0);


  virtual int             calculate_text_width(const char*     text);
  virtual int             calculate_text_width(const wchar_t*  text);
  virtual int             calculate_text_width(const char16_t* text);
  virtual int             calculate_text_width(const char32_t* text);

  virtual int             calculate_text_height(const char*     text);
  virtual int             calculate_text_height(const wchar_t*  text);
  virtual int             calculate_text_height(const char16_t* text);
  virtual int             calculate_text_height(const char32_t* text);

  virtual void            set_text_size(int height_pixels);

  virtual void            draw_svg_from_data(uint8_t* svg_data, int svg_data_length, int offset_x=0, int offset_y=0, int draw_width=0, int draw_height=0);
  virtual bool            draw_svg_from_file(const char* filename, int offset_x=0, int offset_y=0, int draw_width=0, int draw_height=0);
  virtual bool            svg_dimensions_from_file(const char* filename, int& width, int& height);

  virtual void            clear_rect                 (color c, point corner1, point corner2);
  virtual void            draw_line_known_background (pointf p0, pointf p1, color c, color bg);
  virtual void            draw_line                  (pointf p0, pointf p1, color c);
  virtual void            draw_line_vertical         (point p0, point p1, color c);
  virtual void            draw_line_horizontal       (point p0, point p1, color c);
  
  virtual void            draw_circle                (pointf p0, float radius, color c);
  virtual void            draw_triangle              (pointf p0, pointf p1, pointf p2, color c);

  // Event functions
  virtual bool            handle_event               (my_event& me);
  virtual void            claim_events               (window* w=0);
  virtual void            release_events             (window* w=0);
  virtual void            trash_events_until_release ();

  // Utility functions
  virtual class display*  get_display                ();

  // Function for updating data indepently from drawing it
  virtual void            update_data                () {}
  
                          window                     (color bg = BLACK);
  virtual                 ~window                    ();
};




#endif
