Shortcut or menu path to "Rotate to right/left"
-
What I think the problem was is that a newly created script hasn’t been assigned
an ID known to npp. This is normally done during plugin initialization where npp
asks for functions to register, hence the restart of npp solved it. -
@Ekopalypse said in Shortcut or menu path to "Rotate to right/left":
A python script might look like this
import ctypes ROTATION_A_LEFT = 2000 ROTATION_A_RIGHT = 2001 WM_COMMAND = 0x111 def isSingleView(): npp_hwnd = ctypes.windll.user32.FindWindowW(u'Notepad++', None) splitter_hwnd = ctypes.windll.user32.FindWindowExW(npp_hwnd, None, u'splitterContainer', None) return (not bool(ctypes.windll.user32.IsWindowVisible(splitter_hwnd)), splitter_hwnd) def LOWORD(value): return value & 0xFFFF single_view, hwnd = isSingleView() if not single_view: ctypes.windll.user32.SendMessageW(hwnd, WM_COMMAND, LOWORD(ROTATION_A_LEFT), 0)
A few years old but it still works!!! I’ve been wanting a toolbar button for rotating the panes and this is great. Do you know if it would be possible to have the script toggle so that it rotates one way on the first click and back the other way on the next click? As it is, the first click rotates in the desired direction but the next click rotates once more in the same direction which doesn’t return the panes to the order they were in, so it requires three clicks to do that. Obviously, I could just have two buttons, one for right and one for left, but it would save toolbar space if they were combined into one button.
-
Oh dear … When I see this old code, what was I thinking? :-D
let’s create a new property of the notepad class and store the state there.
import ctypes ROTATION_A_LEFT = 2000 ROTATION_A_RIGHT = 2001 WM_COMMAND = 0x111 def isSingleView(): npp_hwnd = ctypes.windll.user32.FindWindowW(u'Notepad++', None) splitter_hwnd = ctypes.windll.user32.FindWindowExW(npp_hwnd, None, u'splitterContainer', None) return (not bool(ctypes.windll.user32.IsWindowVisible(splitter_hwnd)), splitter_hwnd) def LOWORD(value): return value & 0xFFFF if not hasattr(notepad, "rotateSplitView"): notepad.rotateSplitView = False single_view, hwnd = isSingleView() if not single_view: if notepad.rotateSplitView: ctypes.windll.user32.SendMessageW(hwnd, WM_COMMAND, LOWORD(ROTATION_A_LEFT), 0) else: ctypes.windll.user32.SendMessageW(hwnd, WM_COMMAND, LOWORD(ROTATION_A_RIGHT), 0) notepad.rotateSplitView = not notepad.rotateSplitView
But nowadays I guess I would do something like
from ctypes import wintypes, WinDLL from Npp import notepad class ViewRotator(): def __init__(self): self.LOWORD_LEFT = 2000 self.LOWORD_RIGHT = 2001 self.WM_COMMAND = 0x111 self.toggle_rotating_direction = False self.npp_hwnd = WinDLL("user32").FindWindowW(u'Notepad++', None) self.splitter_hwnd = WinDLL("user32").FindWindowExW(self.npp_hwnd, None, u'splitterContainer', None) self.send = WinDLL("user32").SendMessageW self.send.argtypes = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM] self.send.resttype = wintypes.LPARAM # LRESULT def isSingleView(self): return not bool(WinDLL("user32").IsWindowVisible(self.splitter_hwnd)) def rotate(self): if not self.isSingleView(): if self.toggle_rotating_direction: self.send(self.splitter_hwnd, self.WM_COMMAND, self.LOWORD_RIGHT, 0) else: self.send(self.splitter_hwnd, self.WM_COMMAND, self.LOWORD_LEFT, 0) self.toggle_rotating_direction = not self.toggle_rotating_direction if not hasattr(notepad, "rotateSplitView"): notepad.rotateSplitView = ViewRotator().rotate notepad.rotateSplitView()
-
self.send.resttype = wintypes.LPARAM # LRESULT
I think you mean
restype
def isSingleView(self):
…
if not self.isSingleView():Any reason not to use
notepad.isSingleView()
instead of writing a custom function?
Oh dear … When I see this old code, what was I thinking? :-D
Yep, we all feel this way about our own old code. :-)
It’s because we’ve learned so much since the time of original writing. -
@Alan-Kilborn said in Shortcut or menu path to "Rotate to right/left":
I think you mean restype
Yes, I do, thanks for pointing that out.
Any reason not to use notepad.isSingleView() instead of writing a custom function?
No, I just hadn’t thought about whether there were any builtin methods.
Yep, we all feel this way about our own old code. :-)
It’s because we’ve learned so much since the time of original writing.… and still learning … :-D that’s the beauty of this work, at least for me.
-
UPDATED VERSION
from ctypes import wintypes, WinDLL from Npp import notepad class ViewRotator(): def __init__(self): self.LOWORD_LEFT = 2000 self.LOWORD_RIGHT = 2001 self.WM_COMMAND = 0x111 self.toggle_rotating_direction = False self.npp_hwnd = WinDLL("user32").FindWindowW(u'Notepad++', None) self.splitter_hwnd = WinDLL("user32").FindWindowExW(self.npp_hwnd, None, u'splitterContainer', None) self.send = WinDLL("user32").SendMessageW self.send.argtypes = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM] self.send.restype = wintypes.LPARAM # LRESULT def rotate(self): if not notepad.isSingleView(): if self.toggle_rotating_direction: self.send(self.splitter_hwnd, self.WM_COMMAND, self.LOWORD_RIGHT, 0) else: self.send(self.splitter_hwnd, self.WM_COMMAND, self.LOWORD_LEFT, 0) self.toggle_rotating_direction = not self.toggle_rotating_direction if not hasattr(notepad, "rotateSplitView"): notepad.rotateSplitView = ViewRotator().rotate notepad.rotateSplitView()
-
This is an interesting approach to remembering
toggle_rotating_direction
from run to run of the script. Side note: IMO the name of that variable could have been better.If I were writing that script, I might have remembered only the variable in the notepad variable (i.e.,
notepad.toggle_rotating_direction =
…) instead of the function.Your way has the advantage that you’ve added a general purpose function (
notepad.rotateSplitView()
) that could also easily be called by other scripts. -
@Alan-Kilborn said in Shortcut or menu path to "Rotate to right/left":
IMO the name of that variable could have been better
Sure, but I’m constantly struggling to name things.
What would be your choice? change_rotating_direction?…
I had the same thoughts and decided to use a function because it can easily be modified to use a parameter to get either a split landscape or portrait view.
-
IMO the name of that variable could have been better
The reason
toggle_rotating_direction
isn’t good IMO is because, every time the code runs a toggle happens, and not just whentoggle_rotating_direction
is true.what would be your choice?
Hmm, for this one, since it is a boolean, I might go with
next_rotate_is_to_the_right
.With something like that, true/false makes sense.
Of course, this is all up to individual taste.
I’m constantly struggling to name things.
Yes, it is hard sometimes. Often what I do is to name something
zz
orzzz
and just barrel ahead coding with that. Later, like when I’ve completed the local block of code, a good name surfaces and a rename fixes things.I find that if I spend the time up front to come up with a great name, the code to be written changes the meaning somewhat and the great name is no longer great. So I end up taking the time to come up with 2 good names instead of just 1. Naming after the fact seems a viable technique, at least for me.
Of course I don’t do this 100% of the time, just when a suitable name doesn’t immediately come to mind.
-
@Ekopalypse said in Shortcut or menu path to "Rotate to right/left":
UPDATED VERSION
from ctypes import wintypes, WinDLL from Npp import notepad class ViewRotator(): def __init__(self): self.LOWORD_LEFT = 2000 self.LOWORD_RIGHT = 2001 self.WM_COMMAND = 0x111 self.toggle_rotating_direction = False self.npp_hwnd = WinDLL("user32").FindWindowW(u'Notepad++', None) self.splitter_hwnd = WinDLL("user32").FindWindowExW(self.npp_hwnd, None, u'splitterContainer', None) self.send = WinDLL("user32").SendMessageW self.send.argtypes = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM] self.send.restype = wintypes.LPARAM # LRESULT def rotate(self): if not notepad.isSingleView(): if self.toggle_rotating_direction: self.send(self.splitter_hwnd, self.WM_COMMAND, self.LOWORD_RIGHT, 0) else: self.send(self.splitter_hwnd, self.WM_COMMAND, self.LOWORD_LEFT, 0) self.toggle_rotating_direction = not self.toggle_rotating_direction if not hasattr(notepad, "rotateSplitView"): notepad.rotateSplitView = ViewRotator().rotate notepad.rotateSplitView()
Wowsers!!! That is perfect. Thank you so much.