Python Forum
Thread Rating:
  • 1 Vote(s) - 3 Average
  • 1
  • 2
  • 3
  • 4
  • 5
LED control menu
#11
#!/usr/bin/env python

import sys
import time

import dothat.backlight as backlight
import dothat.lcd as lcd
import dothat.touch as nav
from dot3k.menu import Menu, MenuOption
from time import sleep 

# Add the root examples dir so Python can find the plugins
sys.path.append('/home/pi/Pimoroni/displayotron/examples')

from plugins.clock import Clock
from plugins.graph import IPAddress, GraphTemp, GraphCPU, GraphNetSpeed, GraphSysReboot, GraphSysShutdown
from plugins.text import Text
from plugins.utils import Backlight, Contrast

print("""
This advanced example uses the menu framework.
It gives you a basic menu setup with plugins. You should be able to view system info and adjust settings!

Press CTRL+C to exit.
""")

class Lightcontrol(MenuOption):
    """Control; Lights"""
    def __init__(self):
        self.selected_option = 0
        self.options = [
        'On',
        'Off',
        ]
    self.actions = [
    self.handle_On,
    self.handle_Off,
]
    MenuOption.__init__(self)

    def handle_On(self):
        print('Eeek! Doing monkey stuff!')
        time.sleep(2)
        print('Done monkey stuff!')

    def handle_Off(self):
        print("Oook! Doing donkey stuff!")
        time.sleep(2)
        print("Done donkey stuff!")

    def select_option(self):
        self.actions[self.selected_option]()

    def next_option(self):
        self.selected_option = (self.selected_option + 1) % len(self.options)

    def prev_option(self):
        self.selected_option = (self.selected_option - 1) % len(self.options)
    def up(self):
        self.prev_option()
    def down(self):
        self.next_option()
    def right(self):
        self.select_option()

    def get_current_option(self):
        return self.options[self.selected_option]

    def get_next_option(self):
        return self.options[(self.selected_option + 1) % len(self.options)]

    def get_prev_option(self):
        return self.options[(self.selected_option - 1) % len(self.options)]

    def redraw(self, menu):
        menu.write_option(
            row=0,
            margin=1,
            icon='',
            text=self.get_prev_option()
        )

        menu.write_option(
            row=1,
            margin=1,
            icon='>',  # Let's use a > to denote the currently selected option
            text=self.get_current_option()
        )

        menu.write_option(
            row=2,
            margin=1,
            icon='',
            text=self.get_next_option()
        )
    
    
"""
Using a set of nested lists you can describe
the menu you want to display on dot3k.

Instances of classes derived from MenuOption can
be used as menu items to show information or change settings.

See GraphTemp, GraphCPU, Contrast and Backlight for examples.
"""


menu = Menu(
    structure={
            'Power Options': {
                'Reboot':GraphSysReboot(),
                'Shutdown':GraphSysShutdown(),
                },
            'Aquarium': {
                'Lighting': {
                    'Control': Lightcontrol(),
                    }
                },
        'Clock': Clock(backlight),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(backlight),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd=lcd,
    idle_timeout=30,
    input_handler=Text())

"""
You can use anything to control dot3k.menu,
but you'll probably want to use dot3k.touch
"""
nav.bind_defaults(menu)

while 1:
    menu.redraw()
    time.sleep(0.05)
temp.py", line 36, in Lightcontrol
    self.handle_On,
NameError: name 'self' is not defined

also tried changing the indent around a few times
#!/usr/bin/env python

import sys
import time

import dothat.backlight as backlight
import dothat.lcd as lcd
import dothat.touch as nav
from dot3k.menu import Menu, MenuOption
from time import sleep 

# Add the root examples dir so Python can find the plugins
sys.path.append('/home/pi/Pimoroni/displayotron/examples')

from plugins.clock import Clock
from plugins.graph import IPAddress, GraphTemp, GraphCPU, GraphNetSpeed, GraphSysReboot, GraphSysShutdown
from plugins.text import Text
from plugins.utils import Backlight, Contrast

print("""
This advanced example uses the menu framework.
It gives you a basic menu setup with plugins. You should be able to view system info and adjust settings!

Press CTRL+C to exit.
""")

class Lightcontrol(MenuOption):
    """Control; Lights"""
    def __init__(self):
        self.selected_option = 0
        self.options = [
        'On',
        'Off',
        ]
    self.actions = [
    self.handle_On,
    self.handle_Off,
]
    MenuOption.__init__(self)

def handle_On(self):
    print('Eeek! Doing monkey stuff!')
    time.sleep(2)
    print('Done monkey stuff!')

def handle_Off(self):
    print("Oook! Doing donkey stuff!")
    time.sleep(2)
    print("Done donkey stuff!")

def select_option(self):
    self.actions[self.selected_option]()

def next_option(self):
    self.selected_option = (self.selected_option + 1) % len(self.options)

def prev_option(self):
    self.selected_option = (self.selected_option - 1) % len(self.options)

def up(self):
    self.prev_option()

def down(self):
    self.next_option()

def right(self):
    self.select_option()

def get_current_option(self):
    return self.options[self.selected_option]

def get_next_option(self):
    return self.options[(self.selected_option + 1) % len(self.options)]

def get_prev_option(self):
    return self.options[(self.selected_option - 1) % len(self.options)]

def redraw(self, menu):
    menu.write_option(
        row=0,
        margin=1,
        icon='',
        text=self.get_prev_option()
        )

    menu.write_option(
        row=1,
        margin=1,
        icon='>',  # Let's use a > to denote the currently selected option
        text=self.get_current_option()
        )

    menu.write_option(
        row=2,
        margin=1,
        icon='',
        text=self.get_next_option()
        )
    
    
"""
Using a set of nested lists you can describe
the menu you want to display on dot3k.

Instances of classes derived from MenuOption can
be used as menu items to show information or change settings.

See GraphTemp, GraphCPU, Contrast and Backlight for examples.
"""


menu = Menu(
    structure={
            'Power Options': {
                'Reboot':GraphSysReboot(),
                'Shutdown':GraphSysShutdown(),
                },
            'Aquarium': {
                'Lighting': {
                    'Control': Lightcontrol(),
                    }
                },
        'Clock': Clock(backlight),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(backlight),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd=lcd,
    idle_timeout=30,
    input_handler=Text())

"""
You can use anything to control dot3k.menu,
but you'll probably want to use dot3k.touch
"""
nav.bind_defaults(menu)

while 1:
    menu.redraw()
    time.sleep(0.05)
Reply
#12
Self is created when the instance of a class is created. So, there is no self outside the __init__ method. You can remove self. part or do it like this. Try it. I am not really sure of what I am talking about. This is how I understand all that classy classiness Smile

    def __init__(self):
        self.selected_option = 0
        self.options = [
        'On',
        'Off',
        ]
        self.actions = [
            self.handle_On,
            self.handle_Off,
            ]
__init__ method is executed when an instance of a class is created. Self is a reference to that instance. self.object is called instance object and defining one outside of the __init__ method obviously is causing this error.

In the other side are the class objects. You just define them as regular objects inside the class definition

class Foo:
    def __init__(self, obj_1, obj_2, obj_3):
        self.one = obj_1 # instance attribute
        self.two = obj_2 # instance attribute

    three = obj_3 # class attribute
Because class objects are owned by the class they are shared between all instances of that class. While the instance objects are different for every instance of that class.
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#13
#!/usr/bin/env python
 
import sys
import time
 
import dothat.backlight as backlight
import dothat.lcd as lcd
import dothat.touch as nav
from dot3k.menu import Menu, MenuOption
from time import sleep 
 
# Add the root examples dir so Python can find the plugins
sys.path.append('/home/pi/Pimoroni/displayotron/examples')
 
from plugins.clock import Clock
from plugins.graph import IPAddress, GraphTemp, GraphCPU, GraphNetSpeed, GraphSysReboot, GraphSysShutdown
from plugins.text import Text
from plugins.utils import Backlight, Contrast
 
print("""
This advanced example uses the menu framework.
It gives you a basic menu setup with plugins. You should be able to view system info and adjust settings!
 
Press CTRL+C to exit.
""")
 
class Lightcontrol(MenuOption):
    """Control; Lights"""
    def __init__(self):
        self.selected_option = 0
        self.options = [
        'On',
        'Off',
        ]
    self.actions = [
        self.handle_On,
        self.handle_Off,
        ]
    def handle_On(self):
        print('Eeek! Doing monkey stuff!')
        time.sleep(2)
        print('Done monkey stuff!')
 
    def handle_Off(self):
        print("Oook! Doing donkey stuff!")
        time.sleep(2)
        print("Done donkey stuff!")
 
def select_option(self):
    self.actions[self.selected_option]()
 
def next_option(self):
    self.selected_option = (self.selected_option + 1) % len(self.options)
 
def prev_option(self):
    self.selected_option = (self.selected_option - 1) % len(self.options)
 
def up(self):
    self.prev_option()
 
def down(self):
    self.next_option()
 
def right(self):
    self.select_option()
 
def get_current_option(self):
    return self.options[self.selected_option]
 
def get_next_option(self):
    return self.options[(self.selected_option + 1) % len(self.options)]
 
def get_prev_option(self):
    return self.options[(self.selected_option - 1) % len(self.options)]
 
def redraw(self, menu):
    menu.write_option(
        row=0,
        margin=1,
        icon='',
        text=self.get_prev_option()
        )
 
    menu.write_option(
        row=1,
        margin=1,
        icon='>',  # Let's use a > to denote the currently selected option
        text=self.get_current_option()
        )
 
    menu.write_option(
        row=2,
        margin=1,
        icon='',
        text=self.get_next_option()
        )
     
     
"""
Using a set of nested lists you can describe
the menu you want to display on dot3k.
 
Instances of classes derived from MenuOption can
be used as menu items to show information or change settings.
 
See GraphTemp, GraphCPU, Contrast and Backlight for examples.
"""
 
 
menu = Menu(
    structure={
            'Power Options': {
                'Reboot':GraphSysReboot(),
                'Shutdown':GraphSysShutdown(),
                },
            'Aquarium': {
                'Lighting': {
                    'Control': Lightcontrol(),
                    }
                },
        'Clock': Clock(backlight),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(backlight),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd=lcd,
    idle_timeout=30,
    input_handler=Text())
 
"""
You can use anything to control dot3k.menu,
but you'll probably want to use dot3k.touch
"""
nav.bind_defaults(menu)
 
while 1:
    menu.redraw()
    time.sleep(0.05)
line 146, in <module>
    menu.redraw()
    File"/usr/local/lib/python3.5/dist-packages/dot3k/menu.py", line 477 in redraw
        if self.current_value().text_entry:
AttributeError: 'Lightcontrol' object has no attribute 'text_entry'
still trying to get my head around classes, just when i think ive cracked it i get another error haha
Reply
#14
I added some additional content to my previous post. Look at it. Remove the self. before handle_On and handle_Off.

Do you think to indent line 49 to 96? Are they part of the class definition?
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#15
We're nearly there, the code works and i can change which gpio is true or false via the doHAT only problem is when your faced with the on or off options the previous error appears in the shell,
however the on and off also dont scroll so you dont know which is selected it appears like:
Off
>On
Off
you also cant seem to go back once on this screen
#!/usr/bin/env python

import sys
import time

import dothat.backlight as backlight
import dothat.lcd as lcd
import dothat.touch as nav
from dot3k.menu import Menu, MenuOption
from time import sleep 

# Add the root examples dir so Python can find the plugins
sys.path.append('/home/pi/Pimoroni/displayotron/examples')

from plugins.clock import Clock
from plugins.graph import IPAddress, GraphTemp, GraphCPU, GraphNetSpeed, GraphSysReboot, GraphSysShutdown
from plugins.text import Text
from plugins.utils import Backlight, Contrast

import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setup(13,GPIO.OUT)
GPIO.setup(5,GPIO.OUT)

print("""
This advanced example uses the menu framework.
It gives you a basic menu setup with plugins. You should be able to view system info and adjust settings!

Press CTRL+C to exit.
""")

class Lightcontrol(MenuOption):
    """Control; Lights"""
    def __init__(self):
        self.selected_option = 0
        self.options = [
        'On',
        'Off',
        ]
        self.actions = [
            self.handle_On,
            self.handle_Off,
            ]
    def handle_On(self):
        GPIO.output(13,0)
        GPIO.output(5,0)
        GPIO.output(13,1)
        print('ON! Doing monkey stuff!')
        time.sleep(2)
        print('Done monkey stuff!')
        

    def handle_Off(self):
        GPIO.output(5,0)
        GPIO.output(13,0)
        GPIO.output(5,1)
        print("OFF! Doing donkey stuff!")
        time.sleep(2)
        print("Done donkey stuff!")

    def select_option(self):
        self.actions[self.selected_option]()

    def next_option(self):
        self.selected_option = (self.selected_option + 1) % len(self.options)

    def prev_option(self):
        self.selected_option = (self.selected_option - 1) % len(self.options)

    def up(self):
        self.prev_option()

    def down(self):
        self.next_option()

    def right(self):
        self.select_option()

    def get_current_option(self):
        return self.options[self.selected_option]

    def get_next_option(self):
        return self.options[(self.selected_option + 1) % len(self.options)]

    def get_prev_option(self):
        return self.options[(self.selected_option - 1) % len(self.options)]

    def redraw(self, menu):
        menu.write_option(
            row=0,
            margin=1,
            icon='',
            text=self.get_prev_option()
            )

        menu.write_option(
            row=1,
            margin=1,
            icon='>',  # Let's use a > to denote the currently selected option
            text=self.get_current_option()
            )

        menu.write_option(
            row=2,
            margin=1,
            icon='',
            text=self.get_next_option()
            )
    
    
"""
Using a set of nested lists you can describe
the menu you want to display on dot3k.

Instances of classes derived from MenuOption can
be used as menu items to show information or change settings.

See GraphTemp, GraphCPU, Contrast and Backlight for examples.
"""


menu = Menu(
    structure={
            'Power Options': {
                'Reboot':GraphSysReboot(),
                'Shutdown':GraphSysShutdown(),
                },
            'Aquarium': {
                'Lighting': {
                    'Control': Lightcontrol(),
                    }
                },
        'Clock': Clock(backlight),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(backlight),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd=lcd,
    idle_timeout=30,
    input_handler=Text())

"""
You can use anything to control dot3k.menu,
but you'll probably want to use dot3k.touch
"""
nav.bind_defaults(menu)

while 1:
    menu.redraw()
    time.sleep(0.05)

Just tried this think thats what you meant but now i get the name 'handle_on'is not defined again

#!/usr/bin/env python
 
import sys
import time
 
import dothat.backlight as backlight
import dothat.lcd as lcd
import dothat.touch as nav
from dot3k.menu import Menu, MenuOption
from time import sleep 
 
# Add the root examples dir so Python can find the plugins
sys.path.append('/home/pi/Pimoroni/displayotron/examples')
 
from plugins.clock import Clock
from plugins.graph import IPAddress, GraphTemp, GraphCPU, GraphNetSpeed, GraphSysReboot, GraphSysShutdown
from plugins.text import Text
from plugins.utils import Backlight, Contrast
 
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setup(13,GPIO.OUT)
GPIO.setup(5,GPIO.OUT)
 
print("""
This advanced example uses the menu framework.
It gives you a basic menu setup with plugins. You should be able to view system info and adjust settings!
 
Press CTRL+C to exit.
""")
 
class Lightcontrol(MenuOption):
    """Control; Lights"""
    def __init__(self):
        self.selected_option = 0
        self.options = [
        'On',
        'Off',
        ]
        self.actions = [
            handle_On,
            handle_Off,
            ]
    def handle_On(self):
        GPIO.output(13,0)
        GPIO.output(5,0)
        GPIO.output(13,1)
        print('ON! Doing monkey stuff!')
        time.sleep(2)
        print('Done monkey stuff!')
         
 
    def handle_Off(self):
        GPIO.output(5,0)
        GPIO.output(13,0)
        GPIO.output(5,1)
        print("OFF! Doing donkey stuff!")
        time.sleep(2)
        print("Done donkey stuff!")
 
def select_option(self):
    self.actions[self.selected_option]()
 
def next_option(self):
    self.selected_option = (self.selected_option + 1) % len(self.options)
 
def prev_option(self):
    self.selected_option = (self.selected_option - 1) % len(self.options)
 
def up(self):
    self.prev_option()
 
def down(self):
    self.next_option()
 
def right(self):
    self.select_option()
 
def get_current_option(self):
    return self.options[self.selected_option]
 
def get_next_option(self):
    return self.options[(self.selected_option + 1) % len(self.options)]
 
def get_prev_option(self):
    return self.options[(self.selected_option - 1) % len(self.options)]

def redraw(self, menu):
    menu.write_option(
        row=0,
        margin=1,
        icon='',
        text=self.get_prev_option()
        )
 
    menu.write_option(
        row=1,
        margin=1,
        icon='>',  # Let's use a > to denote the currently selected option
        text=self.get_current_option()
        )
 
    menu.write_option(
        row=2,
        margin=1,
        icon='',
        text=self.get_next_option()
        )
     
     
"""
Using a set of nested lists you can describe
the menu you want to display on dot3k.
 
Instances of classes derived from MenuOption can
be used as menu items to show information or change settings.
 
See GraphTemp, GraphCPU, Contrast and Backlight for examples.
"""
 
 
menu = Menu(
    structure={
            'Power Options': {
                'Reboot':GraphSysReboot(),
                'Shutdown':GraphSysShutdown(),
                },
            'Aquarium': {
                'Lighting': {
                    'Control': Lightcontrol(),
                    }
                },
        'Clock': Clock(backlight),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(backlight),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd=lcd,
    idle_timeout=30,
    input_handler=Text())
 
"""
You can use anything to control dot3k.menu,
but you'll probably want to use dot3k.touch
"""
nav.bind_defaults(menu)
 
while 1:
    menu.redraw()
    time.sleep(0.05)
Reply
#16
The redraw method has this 'menu' parameter but I don't see it passed to the class definition.

Here is a simple example of instance method and why you had to remove self:

>>> class Foo:
...     def say(self): # instalnce method
...         print('hello')
... 
>>> Foo.say()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: say() missing 1 required positional argument: 'self' # Foo is the class itself not an instance of that class so no 'self'
>>> foo_obj = Foo()
>>> foo_obj.say() # foo_object is an instace of the Foo class so self is the same instance and you can call that instance method.
hello
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#17
there must be a simpler way, ignoring the icon and the def for right left etc.
im using a dothat.touch libary which scrolls through the rest of the menu just fine
any way of utilizing that for this script?

this is what im trying to reuse for my needs:
class GraphSysShutdown(MenuOption):
    """Shuts down the Raspberry Pi"""

    def __init__(self):
        self.last = self.millis()
        MenuOption.__init__(self)

    def redraw(self, menu):
        shutdown = "sudo shutdown -h now"

        now = self.millis()
        if now - self.last < 1000 * 5:
            return False

        a = run_cmd(shutdown)

        menu.write_row(0, 'RPI Shutdown')
        menu.write_row(1, '')
menu.write_row(2, time.strftime('  %a %H:%M:%S  '))
think its roughly right
Reply
#18
In the examples of the dot3k the instance of the main class is passed as an argument to the Menu:

my_invader = SpaceInvader() # creating an instance

menu = Menu({
        'Space Invader': my_invader,
        'Clock': Clock(),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Volume': Volume(),
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd,
    my_invader, # here it is passed as an argument.
30)
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#19
i think i understand, could you help me with the code?
youve been a great help so far
really is appreciated

just tried this, i dont get errors but cant turn the gpio to true
class Lightcontrol(MenuOption):
    """Control; Lights"""
    def __init__(self):
        self.last = self.millis()
        MenuOption.__init__(self)

    def redraw(self, menu):
        menu.write_row(1,"Turn Lights On?")

        if nav.BUTTON - self.last < 1000 * 5:
            return False
        a = handle_on(self)

    def handle_On(self):
        GPIO.output(13,0)
        GPIO.output(5,0)
        GPIO.output(13,1)
        return
        print('ON! Doing monkey stuff!')
        time.sleep(2)
        print('Done monkey stuff!')
         
 
    def handle_Off():
        GPIO.output(5,0)
        GPIO.output(13,0)
        GPIO.output(5,1)
        print("OFF! Doing donkey stuff!")
        time.sleep(2)
        print("Done donkey stuff!")


     
"""
Using a set of nested lists you can describe
the menu you want to display on dot3k.
 
Instances of classes derived from MenuOption can
be used as menu items to show information or change settings.
 
See GraphTemp, GraphCPU, Contrast and Backlight for examples.
"""

LC = Lightcontrol() 
 
menu = Menu(
    structure={
            'Power Options': {
                'Reboot':GraphSysReboot(),
                'Shutdown':GraphSysShutdown(),
                },
            'Aquarium': {
                'Lighting': {
                    'Control': {
                        'On': LC,
                        }
                    }
                },
        'Clock': Clock(backlight),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(backlight),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd=lcd,
    idle_handler=Lightcontrol,
    idle_timeout=30,
    input_handler=Text())
 
"""
You can use anything to control dot3k.menu,
but you'll probably want to use dot3k.touch
"""
nav.bind_defaults(menu)
 
while 1:
    menu.redraw()
    time.sleep(0.05)
Reply
#20
The examples of the module are not very comprehensive. I see that an instance of the main class is passed to Menu as a parameter.
I see that you are trying something that I was in about to propose before I hit accidentally Back button of my browser and lost the whole post Big Grin

Pass the instance to the Menu, not the class itself.

menu = Menu(
    structure={
            'Power Options': {
                'Reboot':GraphSysReboot(),
                'Shutdown':GraphSysShutdown(),
                },
            'Aquarium': {
                'Lighting': {
                    'Control': {
                        'On': LC,
                        }
                    }
                },
        'Clock': Clock(backlight),
        'Status': {
            'IP': IPAddress(),
            'CPU': GraphCPU(backlight),
            'Temp': GraphTemp()
        },
        'Settings': {
            'Display': {
                'Contrast': Contrast(lcd),
                'Backlight': Backlight(backlight)
            }
        }
    },
    lcd=lcd,
    idle_handler=LC, # here is the change.
    idle_timeout=30,
    input_handler=Text())
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Remote control of the Visual Studio 2013 debug menu using Python MariusTo 0 2,473 Jan-17-2018, 04:58 PM
Last Post: MariusTo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020