1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.IO;
  8 using System.Collections;
  9 
 10 namespace System.Screen
 11 {
 12     public abstract class Message
 13     {
 14         public nothrow Message() : targetWindowHandle(-1)
 15         {
 16         }
 17         public virtual default ~Message();
 18         public abstract nothrow int Id() const;
 19         public virtual nothrow int Size() const
 20         {
 21             return cast<int>(sizeof(int) + sizeof(int));
 22         }
 23         public abstract nothrow string Name() const;
 24         public virtual nothrow bool IsDefaultWriteScreenMessage() const
 25         {
 26             return false;
 27         }
 28         public nothrow int TargetWindowHandle() const
 29         {
 30             return targetWindowHandle;
 31         }
 32         public nothrow void SetTargetWindowHandle(int targetWindowHandle_)
 33         {
 34             targetWindowHandle = targetWindowHandle_;
 35         }
 36         public virtual void Write(MemoryWriter& writer)
 37         {
 38             writer.Write(Id());
 39             writer.Write(targetWindowHandle);
 40         }
 41         public virtual void Read(MemoryReader& reader)
 42         {
 43             targetWindowHandle = reader.ReadInt();
 44         }
 45         public virtual bool Dispatch(Control* control)
 46         {
 47             return false;
 48         }
 49         private int targetWindowHandle;
 50     }
 51     
 52     public abstract class MessageFactoryFunction
 53     {
 54         public abstract Message* CreateMessage();
 55     }
 56     
 57     public class MessageFactory
 58     {
 59         static MessageFactory() : instance(new MessageFactory())
 60         {
 61         }
 62         private MessageFactory()
 63         {
 64         }
 65         public static MessageFactory& Instance()
 66         {
 67             return *instance;
 68         }
 69         public void Register(int messageIdMessageFactoryFunction* factoryFunction)
 70         {
 71             factoryFunctionMap[messageId] = factoryFunction;
 72             factoryFunctions.Add(UniquePtr<MessageFactoryFunction>(factoryFunction));
 73         }
 74         public Message* CreateMessage(int messageId)
 75         {
 76             Map<intMessageFactoryFunction*>.ConstIterator it = factoryFunctionMap.CFind(messageId);
 77             if (it != factoryFunctionMap.CEnd())
 78             {
 79                 MessageFactoryFunction* factoryFunction = it->second;
 80                 Message* message = factoryFunction->CreateMessage();
 81                 return message;
 82             }
 83             else
 84             {
 85                 throw Exception("message id '" + ToString(messageId) + "' not registered with message factory");
 86             }
 87         }
 88         private static UniquePtr<MessageFactory> instance;
 89         private Map<intMessageFactoryFunction*> factoryFunctionMap;
 90         private List<UniquePtr<MessageFactoryFunction>> factoryFunctions;
 91     }
 92     
 93     public Message* ReadMessage(byte* messageDataint messageSize)
 94     {
 95         MemoryReader reader(messageDatamessageSize);
 96         int messageId = reader.ReadInt();
 97         Message* message = MessageFactory.Instance().CreateMessage(messageId);
 98         message->Read(reader);
 99         return message;
100     }
101     
102     public class ConcreteMessageFactoryFunction<T> : MessageFactoryFunction
103     {
104         public override Message* CreateMessage()
105         {
106             T* message = new T();
107             return message;
108         }
109     }
110     
111     public void RegisterMessage<T>(int messageId)
112     {
113         MessageFactory.Instance().Register(messageIdnew ConcreteMessageFactoryFunction<T>());
114     }
115 }