//
// Definition of default Pen/Tablet event driver.
//
// Copyright 2025 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file.  If this
// file is missing or damaged, see the license at:
//
//     https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
//     https://www.fltk.org/bugs.php
//


#ifndef FL_BASE_PEN_EVENTS_H
#define FL_BASE_PEN_EVENTS_H

#include <config.h>
#include <FL/core/pen_events.H>
#include <FL/Fl.H>

#include <map>
#include <memory>


class Fl_Widget;

namespace Fl {

namespace Pen {

/* Pen event data storage.
  A second storage may be useful if the driver needs to collect pen data
  from multiple events, or if one system event can send multiple FLTK events.
*/
typedef struct EventData {
  double x { 0.0 };
  double y { 0.0 };
  double rx { 0.0 };
  double ry { 0.0 };
  double tilt_x { 0.0 };
  double tilt_y { 0.0 };
  double pressure { 1.0 };
  double proximity { 0.0 };
  double barrel_pressure { 0.0 };
  double twist { 0.0 };
  int pen_id { 0 };
  Fl::Pen::State state { (Fl::Pen::State)0 };
  Fl::Pen::State trigger { (Fl::Pen::State)0 };
} EventData;

extern EventData e;


/*
  Widgets and windows must subscribe to pen events. This is to reduce the amount
  of events sent into the widget hierarchy.

  Usually there is a pretty small number of subscribers, so looping through the
  subscriber list should not be an issue.

  All subscribers track their widget. If a widget is deleted while subscribed,
  including during event handling, the driver will remove the subscription.
  There is no need to explicitly unsubscribe.
 */
class Subscriber : public Fl_Widget_Tracker {
public:
  Subscriber(Fl_Widget *w) : Fl_Widget_Tracker(w) { }
};


/*
 Manage a list of subscribers.
 */
class SubscriberList : public std::map<Fl_Widget*, std::shared_ptr<Subscriber>> {
public:
  SubscriberList() = default;
  void cleanup();
  std::shared_ptr<Subscriber> add(Fl_Widget *w);
  void remove(Fl_Widget *w);
};

extern SubscriberList subscriber_list_;
extern std::shared_ptr<Subscriber> pushed_;
extern std::shared_ptr<Subscriber> below_pen_;

/* The base driver for calls by apps into the pen system.

  Most traffic is generated by system events. The data is then converted
  for the FLTK API and stored in Fl::Pen::e. The Pen interface then sends
  the appropriate FLTK events to the subscribers.

  This driver class manages calls from the app into FLTK, including subscriber
  management and queries for driver an pen abilities.
*/
class Driver {
public:
  Driver() = default;
  virtual void subscribe(Fl_Widget* widget);
  virtual void unsubscribe(Fl_Widget* widget);
  virtual void release();
  virtual Trait traits();
  virtual Trait pen_traits(int pen_id);
};

extern Driver& driver;

} // namespace Pen

} // namespace Fl


#endif // FL_BASE_PEN_EVENTS_H
