Forráskód Böngészése

using tkinter for script

johann 5 éve
szülő
commit
ff3c62384c

+ 7 - 0
lazpaint/lazpaintinstance.pas

@@ -48,6 +48,7 @@ type
     procedure ToolColorChanged(Sender: TObject);
     procedure PythonScriptCommand({%H-}ASender: TObject; ACommand, AParam: UTF8String; out
       AResult: UTF8String);
+    procedure PythonBusy({%H-}Sender: TObject);
     function ScriptShowMessage(AVars: TVariableSet): TScriptResult;
     function ScriptInputBox(AVars: TVariableSet): TScriptResult;
 
@@ -678,6 +679,11 @@ begin
   end;
 end;
 
+procedure TLazPaintInstance.PythonBusy(Sender: TObject);
+begin
+  Application.ProcessMessages;
+end;
+
 function TLazPaintInstance.GetShowSelectionNormal: boolean;
 begin
   if FMain <> nil then result := fmain.ShowSelectionNormal
@@ -1334,6 +1340,7 @@ begin
     p := TPythonScript.Create;
     FScriptName := AFilename;
     p.OnCommand:=@PythonScriptCommand;
+    p.OnBusy := @PythonBusy;
     p.Run(AFilename);
     if p.ErrorText<>'' then
     begin

+ 2 - 0
lazpaint/lazpaintmainform.pas

@@ -3536,6 +3536,7 @@ var
   tmi: TTopMostInfo;
 begin
   tmi := LazPaintInstance.HideTopmost;
+  self.Enabled := false;
   try
     dlg := TOpenDialog.Create(nil);
     try
@@ -3554,6 +3555,7 @@ begin
     end;
     dlg.Free;
   finally
+    self.Enabled := true;
     LazPaintInstance.ShowTopmost(tmi);
   end;
 end;

+ 11 - 3
lazpaint/uprocessauto.pas

@@ -18,11 +18,13 @@ uses
 type
   TReceiveLineEvent = procedure(ALine: RawByteString) of object;
   TSendLineMethod = procedure(const ALine: RawByteString) of object;
+  TBusyEvent = procedure(var ASleep: boolean) of object;
 
 procedure RunProcessAutomation(AExecutable: string; AParameters: array of string;
   out ASendLine: TSendLineMethod;
   AOnReceiveOutput: TReceiveLineEvent;
-  AOnReceiveError: TReceiveLineEvent);
+  AOnReceiveError: TReceiveLineEvent;
+  AOnBusy: TBusyEvent);
 
 implementation
 
@@ -42,7 +44,8 @@ type
 procedure RunProcessAutomation(AExecutable: string; AParameters: array of string;
   out ASendLine: TSendLineMethod;
   AOnReceiveOutput: TReceiveLineEvent;
-  AOnReceiveError: TReceiveLineEvent);
+  AOnReceiveError: TReceiveLineEvent;
+  AOnBusy: TBusyEvent);
 
 type
   TReceiveBuffer = record
@@ -110,6 +113,7 @@ var
   p: TAutomatedProcess;
   Output, Error: TReceiveBuffer;
   i: integer;
+  shouldSleep: Boolean;
 begin
   p := TAutomatedProcess.Create(nil);
   ASendLine := @p.SendLine;
@@ -124,7 +128,11 @@ begin
     begin
       if not Receive(p.Output, Output) and
          not Receive(p.Stderr, Error) then
-        sleep(15);
+      begin
+        shouldSleep := true;
+        AOnBusy(shouldSleep);
+        if shouldSleep then sleep(15);
+      end;
     end;
     Receive(p.Output, Output);
     Receive(p.Stderr, Error);

+ 9 - 1
lazpaint/upython.pas

@@ -18,6 +18,7 @@ type
 
   TPythonScript = class
   private
+    FOnBusy: TNotifyEvent;
     FPythonBin: string;
     FPythonVersion: string;
     FLinePrefix: RawByteString;
@@ -30,12 +31,14 @@ type
     function GetPythonVersionMajor: integer;
     procedure PythonError(ALine: RawByteString);
     procedure PythonOutput(ALine: RawByteString);
+    procedure PythonBusy(var ASleep: boolean);
   public
     constructor Create(APythonBin: string = DefaultPythonBin);
     procedure Run(AScriptFilename: UTF8String; APythonVersion: integer = 3);
     property OnOutputLine: TReceiveLineEvent read FOnOutputLine write FOnOutputLine;
     property OnError: TReceiveLineEvent read FOnError write FOnError;
     property OnCommand: TCommandEvent read FOnCommand write FOnCommand;
+    property OnBusy: TNotifyEvent read FOnBusy write FOnBusy;
     property PythonVersion: string read FPythonVersion;
     property PythonVersionMajor: integer read GetPythonVersionMajor;
     property ErrorText: UTF8String read FErrorText;
@@ -147,6 +150,11 @@ begin
   end;
 end;
 
+procedure TPythonScript.PythonBusy(var ASleep: boolean);
+begin
+  if Assigned(FOnBusy) then FOnBusy(self);
+end;
+
 constructor TPythonScript.Create(APythonBin: string);
 begin
   FPythonBin := APythonBin;
@@ -183,7 +191,7 @@ begin
         '%1',inttostr(APythonVersion),[]),
         '%2',inttostr(PythonVersionMajor),[]) );
   FFirstOutput:= true;
-  RunProcessAutomation(FPythonBin, ['-u', AScriptFilename], FPythonSend, @PythonOutput, @PythonError);
+  RunProcessAutomation(FPythonBin, ['-u', AScriptFilename], FPythonSend, @PythonOutput, @PythonError, @PythonBusy);
   FPythonSend := nil;
 end;
 

+ 115 - 17
scripts/layer_shadow.py

@@ -1,26 +1,124 @@
-from lazpaint import colors, image, layer, filters, dialog, tools
+from lazpaint import dialog
+
+try:
+    from tkinter import *
+except ImportError:
+    dialog.show_message("Please install tkinter.")
+    exit()
+        
+from lazpaint import colors, image, layer, filters, tools
 
-chosen_radius = 10
 if layer.is_empty():
     dialog.show_message("Layer is empty")
     exit()
 
-layer.duplicate()
-shadow_index = image.get_layer_index()
-image.move_layer_index(shadow_index, shadow_index-1)
-colors.lightness(shift=-1)
-opacity = layer.get_opacity() 
-layer.set_opacity(opacity*2/3)
+############ image processing
 
-while True:
-    filters.blur(radius=chosen_radius)
-    tools.choose(tools.MOVE_LAYER)
-    tools.mouse([(0,0),(10,10)])
-    new_radius = dialog.input_value("Radius:", chosen_radius)
-    if new_radius == chosen_radius:
-        break
-    else:
-        chosen_radius = new_radius
+chosen_radius = 10
+chosen_offset = (10, 10)
+
+#create shadow layer
+shadow_layer_done = False
+def undo_shadow_layer():
+    global shadow_layer_done
+    if shadow_layer_done:
+        image.undo()
+        image.undo()
         image.undo()
         image.undo()
+        shadow_layer_done = False 
+
+def create_shadow_layer():
+    global shadow_layer_done
+    layer.duplicate()
+    shadow_index = image.get_layer_index()
+    image.move_layer_index(shadow_index, shadow_index-1)
+    colors.lightness(shift=-1)
+    opacity = layer.get_opacity() 
+    layer.set_opacity(opacity*2/3)
+    shadow_layer_done = True
+
+blur_done = False
+def undo_blur():
+    global blur_done
+    if blur_done:
+        image.undo()
+        image.undo()
+        blur_done = False
+
+def apply_blur():
+    global blur_done
+    undo_blur()
+    filters.blur(radius=chosen_radius)
+    tools.choose(tools.MOVE_LAYER)
+    tools.mouse([(0,0), chosen_offset])
+    blur_done = True
+
+######## interface
+
+def button_ok_click():
+    exit()
+
+def button_cancel_click():
+    undo_blur()
+    undo_shadow_layer()
+    exit()
+
+scale_radius_update_job = None
+
+def scale_radius_update_do():
+    global scale_radius_update_job, chosen_radius, scale_radius
+    chosen_radius = scale_radius.get()
+    apply_blur()
+    scale_radius_update_job = None    
+
+def scale_radius_update(event):
+    global window, scale_radius_update_job
+    if scale_radius_update_job:
+        window.after_cancel(scale_radius_update_job)
+    scale_radius_update_job = window.after(500, scale_radius_update_do)    
+
+window = Tk()
+window.title("Layer shadow")
+window.resizable(False, False)
+
+frame = Frame(window)
+frame.pack()
+
+label_radius = Label(frame, text="Radius:")
+label_radius.grid(column=0, row=0)
+scale_radius = Scale(frame, from_=1, to=100, orient=HORIZONTAL, command=scale_radius_update)
+scale_radius.grid(column=1, row=0, columnspan=2, sticky=W+E, padx=10)
+scale_radius.set(chosen_radius)
+
+label_offset = Label(frame, text="Offset:")
+label_offset.grid(column=0, row=1)
+scale_offset_x = Scale(frame, from_=-100, to=100, orient=HORIZONTAL)
+scale_offset_x.grid(column=1, row=1, sticky=W+E, padx=10)
+scale_offset_x.set(chosen_offset[0])
+scale_offset_y = Scale(frame, from_=-100, to=100, orient=HORIZONTAL)
+scale_offset_y.grid(column=2, row=1, sticky=W+E, padx=10)
+scale_offset_y.set(chosen_offset[1])
+
+frame.columnconfigure(0, pad=20)
+frame.columnconfigure(1, weight=1)
+frame.columnconfigure(2, weight=1)
+frame.rowconfigure(0, pad=20)
+frame.rowconfigure(1, pad=20)
+
+button_ok = Button(window, text="Ok", command=button_ok_click)
+button_ok.pack(side=RIGHT, padx=10, pady=10)
+button_cancel = Button(window, text="Cancel", command=button_cancel_click)
+button_cancel.pack(side=RIGHT, pady=10)
+
+create_shadow_layer()
+apply_blur()
+
+window.update()
+window_width = window.winfo_width()
+screen_width = window.winfo_screenwidth()
+window.geometry('+%d+0' % (int((screen_width - window_width) / 2)))
+
+window.mainloop()
 
+button_cancel_click()