[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r5490 - in grc/branches/gtk_separation: notes src src/
From: |
jblum |
Subject: |
[Commit-gnuradio] r5490 - in grc/branches/gtk_separation: notes src src/Elements src/Graphics src/Graphics/GraphicalElements src/Graphics/Windows src/SignalBlockDefs |
Date: |
Thu, 17 May 2007 20:34:10 -0600 (MDT) |
Author: jblum
Date: 2007-05-17 20:34:09 -0600 (Thu, 17 May 2007)
New Revision: 5490
Added:
grc/branches/gtk_separation/src/Elements/Utils.py
grc/branches/gtk_separation/src/Graphics/GraphicalElements/
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalConnection.py
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalElement.py
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalParam.py
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSignalBlock.py
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSocket.py
grc/branches/gtk_separation/src/Graphics/GraphicalElements/__init__.py
grc/branches/gtk_separation/src/Graphics/__init__.py
Removed:
grc/branches/gtk_separation/src/Graphics/Elements/
Modified:
grc/branches/gtk_separation/notes/notes.txt
grc/branches/gtk_separation/src/Elements/Connection.py
grc/branches/gtk_separation/src/Elements/Element.py
grc/branches/gtk_separation/src/Elements/Param.py
grc/branches/gtk_separation/src/Elements/SignalBlock.py
grc/branches/gtk_separation/src/Elements/Socket.py
grc/branches/gtk_separation/src/Elements/__init__.py
grc/branches/gtk_separation/src/FlowGraphApp.py
grc/branches/gtk_separation/src/Graphics/ActionHandler.py
grc/branches/gtk_separation/src/Graphics/Actions.py
grc/branches/gtk_separation/src/Graphics/Colors.py
grc/branches/gtk_separation/src/Graphics/Messages.py
grc/branches/gtk_separation/src/Graphics/Preferences.py
grc/branches/gtk_separation/src/Graphics/StateCache.py
grc/branches/gtk_separation/src/Graphics/Windows/Bars.py
grc/branches/gtk_separation/src/Graphics/Windows/Dialogs.py
grc/branches/gtk_separation/src/Graphics/Windows/FlowGraph.py
grc/branches/gtk_separation/src/Graphics/Windows/FlowGraphFileDialog.py
grc/branches/gtk_separation/src/Graphics/Windows/MainWindow.py
grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockParamsDialog.py
grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockSelectionWindow.py
grc/branches/gtk_separation/src/Graphics/Windows/USRPDiagnostics.py
grc/branches/gtk_separation/src/Graphics/Windows/VariableModificationWindow.py
grc/branches/gtk_separation/src/Graphics/Windows/__init__.py
grc/branches/gtk_separation/src/Run.py
grc/branches/gtk_separation/src/SignalBlockDefs/__init__.py
Log:
separated param,connection,socket,signalblock into graphical and non graphical
directories
Modified: grc/branches/gtk_separation/notes/notes.txt
===================================================================
--- grc/branches/gtk_separation/notes/notes.txt 2007-05-18 01:08:54 UTC (rev
5489)
+++ grc/branches/gtk_separation/notes/notes.txt 2007-05-18 02:34:09 UTC (rev
5490)
@@ -16,6 +16,7 @@
-create sub-flow graphs to be used in larger flow graphs
-math expressions, pi, e, sin, cos, tan, log, ln
-stdin/out communication protocal
+-separate flowgraph into graphical and non graphical
############ wxPython Features: ####################
-dump wx running graph to png?
Modified: grc/branches/gtk_separation/src/Elements/Connection.py
===================================================================
--- grc/branches/gtk_separation/src/Elements/Connection.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Elements/Connection.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -19,25 +19,20 @@
"""
Elements/Connection.py
Josh Blum
- The graphical connection for input/output sockets.
+ The elemental connection of input and output sockets.
"""
-from Elements import *
-from Element import Element
-from DataType import can_connect
+from Element import Element
+import Utils
-def get_angle_from_coordinates((x1,y1), (x2,y2)):
- """ given two points, calculate the vector direction from point1 to
point2,
- directions are multiples of 90 degrees. """
- if y1 == y2:#0 or 180
- if x2 > x1: return 0
- else: return 180
- else:#90 or 270
- if y2 > y1: return 270
- else: return 90
+class InvalidConnectionException(Exception):
+ def __str__(self): return 'A connection requires a valid input and
output socket!'
+class TooManyConnectionsException(Exception):
+ def __str__(self): return 'An input socket may only have one
connection!'
+
class Connection(Element):
- """ Connection is a graphical connection for sockets """
+ """ Connection provides elemental interfaces for a connection of
sockets. """
type = 'connection'
def __init__(self, parent, socket1, socket2):
""" Initialize the Element and set the parent, coor, and
rotation.
@@ -53,11 +48,11 @@
# socket1 =
socket1.get_connections()[0].get_output_socket() #so we use its output
socket
#if is_input_socket(socket2) and socket2.is_connected(): #same
for socket2
# socket2 =
socket2.get_connections()[0].get_output_socket()
- if is_input_socket(socket1) and is_output_socket(socket2):
+ if Utils.is_input_socket(socket1) and
Utils.is_output_socket(socket2):
socket1.connect(self) #order is important, try input
socket first (since input can throw an exception)
socket2.connect(self)
self.sockets = [socket1, socket2]
- elif is_input_socket(socket2) and is_output_socket(socket1):
+ elif Utils.is_input_socket(socket2) and
Utils.is_output_socket(socket1):
socket2.connect(self) #order is important, try input
socket first (since input can throw an exception)
socket1.connect(self)
self.sockets = [socket2, socket1]
@@ -77,68 +72,8 @@
def get_output_socket(self):
"""get the output socket"""
- return self.sockets[1]
+ return self.sockets[1]
- def update(self):
- """ add the horizontal and vertical lines that will connect
the two parameters """
- self.clear()
- input_socket = self.get_input_socket()
- output_socket = self.get_output_socket()
- deltaAngle = abs(output_socket.get_connector_direction() -
input_socket.get_connector_direction())
- (x1, y1) = output_socket.get_connector_coordinates()[1]
- self.add_line(*output_socket.get_connector_coordinates())
- (x2, y2) = input_socket.get_connector_coordinates()[1]
- self.add_line(*input_socket.get_connector_coordinates())
- if deltaAngle == 180:
- W = abs(x1 - x2)
- H = abs(y1 - y2)
- midX = (x1+x2)/2
- midY = (y1+y2)/2
- sW = x1 - x2
- if output_socket.get_connector_direction() == 0: sW =
sW * -1
- sH = y1 - y2
- if output_socket.get_connector_direction() == 270: sH =
sH * -1
- if ((W>H or sW<0) and
is_horizontal(output_socket.get_connector_direction())) or\
- (W>=H and sH>=0 and
is_vertical(output_socket.get_connector_direction())):
- self.add_line((x1,y1),(x1,midY))
- self.add_line((x1,midY),(x2,midY))
- self.add_line((x2,y2),(x2,midY))
- elif (H>=W and sW>=0 and
is_horizontal(output_socket.get_connector_direction())) or\
- ((H>W or sH<0) and
is_vertical(output_socket.get_connector_direction())):
- self.add_line((x1,y1),(midX,y1))
- self.add_line((midX,y1),(midX,y2))
- self.add_line((x2,y2),(midX,y2))
- else:
- p1 = (x1, y2)
- p2 = (x2, y1)
- if get_angle_from_coordinates((x1,y1),p1) ==
(output_socket.get_connector_direction()+180)%360 or\
- get_angle_from_coordinates((x2,y2),p1) ==
(input_socket.get_connector_direction()+180)%360: p = p2
- else: p = p1
- self.add_line((x1,y1),p)
- self.add_line((x2,y2),p)
-
- def draw(self, window):
- """ draw the Connection """
- self.update()
- Element.draw(self, window)
- gc = self.gc
- ''' draw error lines around the existing lines when data
types do not match '''
- if not self.is_valid():
- gc.foreground = self.ERROR_color
- for (x1, y1),(x2, y2) in
self.lines_dict[self.get_rotation()]:
- if x1 == x2 and x1 > 0 and x2 > 0: #vertical
- window.draw_line(gc, x1-1, y1, x2-1, y2)
- window.draw_line(gc, x1+1, y1, x2+1, y2)
- elif y1 == y2 and y1 > 0 and y2 > 0: #horizontal
- window.draw_line(gc, x1, y1-1, x2, y2-1)
- window.draw_line(gc, x1, y1+1, x2, y2+1)
-
- def is_valid(self):
- """ is this connection valid, ie: do the input and output data
types match? """
- import Preferences #preferences
- return not Preferences.check_connections() or\
- can_connect(self.sockets[0].get_data_type(),
self.sockets[1].get_data_type())
-
def disconnect(self):
""" delete this connection by calling the socket's disconnect
methods. """
print "disconnecting"
Modified: grc/branches/gtk_separation/src/Elements/Element.py
===================================================================
--- grc/branches/gtk_separation/src/Elements/Element.py 2007-05-18 01:08:54 UTC
(rev 5489)
+++ grc/branches/gtk_separation/src/Elements/Element.py 2007-05-18 02:34:09 UTC
(rev 5490)
@@ -19,19 +19,14 @@
"""
Elements/Element.py
Josh Blum
- base class for graphical elements such as:
+ The base class for graphical elements such as:
signal blocks, input sockets, output sockets and connections
"""
-from Constants import *
-from Elements import *
-import Colors
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
+from Constants import POSSIBLE_ROTATIONS
+
class Element:
- """ Element is the base class for all graphical elements. It
contains an X,Y coordinate, a list
+ """ Element is the base class for all elements. It contains an X,Y
coordinate, a list
of rectangular areas that the element occupies and methods to detect
selection. """
def __init__(self, parent, coor, rotation):
""" make a new list of rectangular areas and lines, and set
the coordinate and the rotation """
@@ -39,13 +34,7 @@
self.set_rotation(rotation)
self.set_coordinate(coor)
self.clear()
- self.highlighted = False
- #setup colors
- self.BG_color = Colors.BG_COLOR
- self.FG_color = Colors.FG_COLOR
- self.H_color = Colors.H_COLOR
- self.TXT_color = Colors.TXT_COLOR
- self.ERROR_color = Colors.ERROR_COLOR
+ self.highlighted = False
def clear(self):
''' make the lines and areas empty. '''
@@ -116,33 +105,8 @@
if (x1 == x2 and x >= x2-maxDist and x <= x2+maxDist
and y <= max(y1,y2) and y >= min(y1,y2)) or\
(y1 == y2 and y >= y2-maxDist and y <=
y2+maxDist and x <= max(x1,x2) and x >= min(x1,x2)):
return self
- return None
-
- def draw(self, window):
- """ draw in the given window. """
- gc = self.get_parent().gc
- self.gc = gc
- X,Y = self.get_coordinate()
- for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
- aX = X + rX
- aY = Y + rY
- gc.foreground = self.BG_color
- window.draw_rectangle(gc, True, aX, aY, W, H)
- if self.is_highlighted(): gc.foreground = self.H_color
- else: gc.foreground = self.FG_color
- window.draw_rectangle(gc, False, aX, aY, W, H)
- for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]:
- if self.is_highlighted(): gc.foreground = self.H_color
- else: gc.foreground = self.FG_color
- window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
+ return None
- def rotate(self, direction):
- """ rotate all of the areas by 90 degrees, direction is
"left"/"right" """
- if direction == gtk.DIR_LEFT: delta_rotation = 90
- elif direction == gtk.DIR_RIGHT: delta_rotation = 270
- self.set_rotation((self.get_rotation() + delta_rotation)%360)
- self.update()
-
def get_rotation(self):
""" get the rotation """
return self.rotation
@@ -154,5 +118,9 @@
possible rotations: '+str(POSSIBLE_ROTATIONS)
sys.exit(1)
self.rotation = rotation
+
+ def update(self):
+ """ Do nothing for the update. """
+ pass
\ No newline at end of file
Modified: grc/branches/gtk_separation/src/Elements/Param.py
===================================================================
--- grc/branches/gtk_separation/src/Elements/Param.py 2007-05-18 01:08:54 UTC
(rev 5489)
+++ grc/branches/gtk_separation/src/Elements/Param.py 2007-05-18 02:34:09 UTC
(rev 5490)
@@ -19,100 +19,12 @@
"""
Elements/Param.py
Josh Blum
- GTK objects for handling input and the signal block parameter class.
+ A signal block parameter.
"""
-from DataType import *
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
-import gobject
-from Constants import *
-from os import path
-
-######################################################################################################
-# gtk objects for handling input
-######################################################################################################
-
-class InputParam(gtk.HBox):
- """ The base class for an input parameter inside the input parameters
dialog. """
- def __init__(self, data_type, handle_changed):
- gtk.HBox.__init__(self)
- self.show()
- self.data_type = data_type
- self.handle_changed = handle_changed
- self.label = gtk.Label('') #no label, markup is added by
set_markup
- self.label.set_size_request(140,30)
- self.label.show()
- self.pack_start(self.label, False)
- self.set_markup = lambda m: self.label.set_markup(m)
-
-class EntryParam(InputParam):
- """ Provide an entry box for strings and numbers. """
- def __init__(self, *args):
- InputParam.__init__(self, *args)
- self.entry = input = gtk.Entry()
- input.set_text(self.data_type.get_data())
- input.connect("changed", self.handle_changed)
- input.show()
- self.pack_start(input, False)
- self.get_text = input.get_text
-
-class FileParam(EntryParam):
- """ Provide an entry box for filename and a button to browse for a
file. """
- def __init__(self, *args):
- EntryParam.__init__(self, *args)
- input = gtk.Button('...')
- input.connect('clicked', self.handle_clicked)
- input.show()
- self.pack_start(input, False)
-
- def handle_clicked(self, widget=None):
- """ If the button was clicked, open a file dialog in open/save
format.
- Replace the text in the entry with the new filename from the
file dialog. """
- file_path = self.data_type.parse()
- # bad file paths will be redirected to default #
- if not path.exists(path.dirname(file_path)): file_path =
DEFAULT_FILE_PATH
- if self.data_type.get_type() == FileOpen().get_type():
- file_dialog = gtk.FileChooserDialog('Open a Data
File...', None,
- gtk.FILE_CHOOSER_ACTION_OPEN,
('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK))
- elif self.data_type.get_type() == FileSave().get_type():
- file_dialog = gtk.FileChooserDialog('Save a Data
File...', None,
- gtk.FILE_CHOOSER_ACTION_SAVE,
('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK))
- file_dialog.set_do_overwrite_confirmation(True)
- file_dialog.set_current_name(path.basename(file_path))
#show the current filename
- file_dialog.set_current_folder(path.dirname(file_path))
#current directory
- file_dialog.set_select_multiple(False)
- file_dialog.set_local_only(True)
- if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog
- file_path = file_dialog.get_filename() #get the file
path
- self.entry.set_text(file_path)
- self.handle_changed()
- file_dialog.destroy() #destroy the dialog
-
-class EnumParam(InputParam):
- """ Provide an entry box for Enum types with a drop down menu. """
- def __init__(self, *args):
- InputParam.__init__(self, *args)
- input = gtk.ComboBox(gtk.ListStore(gobject.TYPE_STRING))
- cell = gtk.CellRendererText()
- input.pack_start(cell, True)
- input.add_attribute(cell, 'text', 0)
- for cname in self.data_type.get_cnames_list():
input.append_text(cname)
- input.set_active(int(self.data_type.get_data()))
- input.show()
- input.connect("changed", self.handle_changed)
- self.pack_start(input, False)
- self.get_text = lambda: str(input.get_active()) #the get text
parses the selected index to a string
-
-######################################################################################################
-# A Parameter, hold a data type and a cname
-######################################################################################################
-
class Param:
""" This class holds a single signal block parameter,
- a data type and a cname, and methods for display. """
+ a data type and a cname. """
def __init__(self, cname, data_type):
""" Initialize by setting the data type and cname. """
self.cname = cname
@@ -126,84 +38,4 @@
def get_data_type(self):
""" Get the data type. """
return self.data_type
-
- def get_input_object(self):
- """ Get the graphical gtk class to represent this parameter.
- Create the input object with this data type and the handle
changed method."""
- if self.get_data_type().get_base_type() ==
Enum().get_base_type(): input = EnumParam
- elif self.get_data_type().get_base_type() ==
File().get_base_type(): input = FileParam
- else: input = EntryParam
- self.input = input(self.get_data_type(), self.handle_changed)
- self.handle_changed()
- return self.input
-
- def handle_changed(self, widget=None):
- ''' if the input changed, write the inputs to the param.
'''
- data_type = self.get_data_type()
- new_data = self.input.get_text()
- old_data = data_type.get_data()
- if old_data != new_data: data_type.set_data(new_data)
- # Set the markup on the label, red for errors in
cooresponding data type. #
- cname = self.get_cname()
- if not data_type.is_valid(): self.input.set_markup('<span
foreground="red"><b>'+cname+'</b></span>')
- else: self.input.set_markup(cname)
-
- def get_markup(self):
- """ Create a markup to display the Param as a label on the
SignalBlock.
- If the data type is an Enum type, use the cname of the Enum's
current choice.
- Otherwise, use parsed the data type and use its string
representation.
- If the data type is not valid, use a red foreground color.
"""
-
###########################################################################
- # display logic for numbers
-
###########################################################################
- def float_to_str(var):
- if var-int(var) == 0: return '%d'%int(var)
- if var*10-int(var*10) == 0: return '%.1f'%var
- if var*100-int(var*100) == 0: return '%.2f'%var
- if var*1000-int(var*1000) == 0: return '%.3f'%var
- else: return '%.3g'%var
- def to_str(var):
- if type(var) == type(str()): return var
- elif type(var) == type(complex()):
- if var.imag == var.real == 0: return '0'
#value is zero
- elif var.imag == 0: return
'%s'%float_to_str(var.real) #value is real
- elif var.real == 0: return
'%sj'%float_to_str(var.imag) #value is imaginary
- elif var.imag < 0: return
'%s-%sj'%(float_to_str(var.real), float_to_str(var.imag*-1))
- else: return '%s+%sj'%(float_to_str(var.real),
float_to_str(var.imag))
- elif type(var) == type(float()): return
float_to_str(var)
- elif type(var) == type(int()): return '%d'%var
- else: return var
-
###########################################################################
- if self.get_data_type().is_valid():
- data = self.get_data_type().parse()
- if self.get_data_type().get_base_type() ==
Enum().get_base_type(): #enum types
- dt_str = self.get_data_type().get_cname()
- elif self.get_data_type().get_base_type() ==
File().get_base_type(): #file types
- suggested_length = 30
- if len(data) <= suggested_length: dt_str = data
- else: #truncate the tail if there is not
enough space
- tail,head = path.split(data)
- if len(head) >= suggested_length:
dt_str = head
- else: dt_str =
tail[0:suggested_length-len(head)] + '...' + head
- elif self.get_data_type().get_base_type() ==
Vector().get_base_type(): #vector types
- # only keep the first X elements of the
list,
- X = 4 #display more for non complex vectors
- dt_str = '[' # replace the
removed elements with a '...'
- for i,e in enumerate(data):
- if i < X or i > len(data)-2: #leave
one on the end
- dt_str = dt_str + to_str(e)
- if i < len(data)-1 and i+1 !=
X: dt_str = dt_str + ', '
- elif i == X: dt_str = dt_str + ' ... '
- dt_str = dt_str + ']'
- elif self.get_data_type().get_type() ==
Hex().get_type(): dt_str = hex(data) #hex, base 16
- else: dt_str = to_str(data) #other types
- return '<b>%s:</b> %s'%(self.cname, dt_str)
- else: return '<span foreground="red"><b>%s:</b>
error</span>'%self.cname
-
- def get_layout(self):
- """ Create a layout based on the current Param's Markup.
"""
- layout = gtk.DrawingArea().create_pango_layout('')
- layout.set_markup(self.get_markup())
- desc = pango.FontDescription(PARAM_FONT)
- layout.set_font_description(desc)
- return layout
+
Modified: grc/branches/gtk_separation/src/Elements/SignalBlock.py
===================================================================
--- grc/branches/gtk_separation/src/Elements/SignalBlock.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Elements/SignalBlock.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -19,22 +19,22 @@
"""
Elements/SignalBlock.py
Josh Blum
- the graphical signal block
+ The elemental signal block
"""
-from Elements import *
from Element import Element
-from DataType import *
-from Constants import *
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
+import Utils
+from Socket import OutputSocket,InputSocket
+from Param import Param
+from DataType import Enum,Int
class SignalBlock(Element):
- """ SignalBlock is a graphical signal block. It is a Element with
an index from the list of
+ """ SignalBlock is an Element with an index from the list of
possible signal blocks and graphical input/output elements. """
type = 'signal block'
+ param_constructor = Param
+ input_socket_constructor = InputSocket
+ output_socket_constructor = OutputSocket
def __init__(self, parent, coor, rotation, tag, id):
""" initialize the signalblock, adding lists for sockets,
params """
Element.__init__(self, parent, coor, rotation)
@@ -50,35 +50,6 @@
self.H = self.W = 0
self.docs = None
- def modify_type_controller(self, direction):
- """ If a type controller was set, increment/decrement its index
by 1, use a % to stay in bounds.
- Direction may be +1 or -1"""
- if self.type_controller != None and
self.type_controller.get_type() == Enum().get_type():
- num_choices =
len(self.type_controller.get_cnames_list())
- index = int(self.type_controller.get_data())
-
self.type_controller.set_data((index+direction+num_choices)%num_choices)
- self.get_parent().update()
- return True
- return False
-
- def modify_socket_controller(self, direction):
- """ If a socket controller was set, increment/decrement its
data type by 1, DO NOT go out of bounds.
- Return True if operation was done. Return False if
operation could not be completed.
- If there is a controller on input and outputs, show
preference to the output controller.
- Direction may be +1 or -1. """
- # Get the socket controller, if there is an input and output
controller, use output #
- socket_controller = None
- if self.input_sockets_controller != None: socket_controller =
self.input_sockets_controller
- elif self.output_sockets_controller != None: socket_controller
= self.output_sockets_controller
- if socket_controller != None and socket_controller.is_valid()
and socket_controller.get_type() == Int().get_type():
- old_data = socket_controller.get_data()
- socket_controller.set_data(socket_controller.parse() +
direction)
- if socket_controller.is_valid(): #modification was
successful
- self.get_parent().update()
- return True
- else: socket_controller.set_data(old_data)
#restore previous value
- return False
-
def get_docs(self):
''' Get a string with helpful hints, suggestions, and
documentation on using this block. '''
return self.docs
@@ -93,13 +64,13 @@
def get_input_socket(self, index):
''' Get the input socket at index. '''
- for socket in filter(is_input_socket, self.get_sockets()):
+ for socket in filter(Utils.is_input_socket, self.get_sockets()):
if socket.get_index() == index: return socket
return None
def get_output_socket(self, index):
''' Get the output socket at index. '''
- for socket in filter(is_output_socket, self.get_sockets()):
+ for socket in filter(Utils.is_output_socket,
self.get_sockets()):
if socket.get_index() == index: return socket
return None
@@ -117,19 +88,8 @@
def get_params(self):
''' Get the params list. '''
- return self.params
-
- def is_valid(self):
- ''' This block is valid if all the params are valid and all
sockets connected. '''
- import Preferences
- if Preferences.check_params(): #preferences
- for param in self.params:
- if not param.get_data_type().is_valid(): return
False
- if Preferences.check_sockets(): #preferences
- for socket in self.get_sockets():
- if not socket.is_valid(): return False
- return True
-
+ return self.params
+
def get_num_input_sockets(self):
''' Get the number of sockets of input type. '''
return len(self.input_sockets)
@@ -140,11 +100,11 @@
def add_input_socket(self, cname, data_type, optional=False, vlen=None):
''' Append an input socket with its cname and data type.
'''
- self.input_sockets.append(InputSocket(self, cname,
self.get_num_input_sockets(), data_type, optional, vlen))
+ self.input_sockets.append(self.input_socket_constructor(self,
cname, self.get_num_input_sockets(), data_type, optional, vlen))
def add_output_socket(self, cname, data_type, optional=False,
vlen=None):
''' Append an output socket with its cname and data type.
'''
- self.output_sockets.append(OutputSocket(self, cname,
self.get_num_output_sockets(), data_type, optional, vlen))
+ self.output_sockets.append(self.output_socket_constructor(self,
cname, self.get_num_output_sockets(), data_type, optional, vlen))
def add_param(self, cname, data_type, show_label=True, type=False,
output_sockets_controller=False, input_sockets_controller=False):
''' Append a param with its cname and data type.
@@ -152,103 +112,19 @@
The type boolean flag registers this parameter to be
controlled via keypress.
The output_sockets_controller registers this parameter
to set the number of output sockets.
The input_sockets_controller registers this parameter
to set the number of input sockets. '''
- param = Param(cname, data_type)
+ param = self.param_constructor(cname, data_type)
if show_label: self.displayed_params.append(param)
if type: self.type_controller = data_type
if output_sockets_controller: self.output_sockets_controller =
data_type
if input_sockets_controller: self.input_sockets_controller =
data_type
self.params.append(param)
- def update(self):
- """ update the block and parameters and sockets when a change
occurs """
- self.clear()
- self._adjust_sockets()
- self._create_labels()
- self.W = self.label_width + 2*LABEL_PADDING_WIDTH
- max_sockets = max(self.get_num_input_sockets(),
self.get_num_output_sockets(), 1)
- self.H = max(self.label_height+2*LABEL_PADDING_HEIGHT,
2*SOCKET_BORDER_SEPARATION + max_sockets*SOCKET_HEIGHT +
(max_sockets-1)*SOCKET_SEPARATION)
- if is_horizontal(self.get_rotation()):
self.add_area((0,0),(self.W,self.H))
- elif is_vertical(self.get_rotation()):
self.add_area((0,0),(self.H,self.W))
- for socket in self.get_sockets(): socket.update()
-
- def _adjust_sockets(self):
- ''' Use the input/output socket controllers to adjust the
number of sockets. '''
- for sockets_list,controller,constructor in
((self.input_sockets, self.input_sockets_controller, InputSocket),
-
(self.output_sockets,
self.output_sockets_controller, OutputSocket)):
- if controller != None and controller.is_valid(): #must
be valid before trying to use the value
- if controller.get_base_type() ==
Vector().get_base_type(): new_num_sockets = len(controller.parse())
- else: new_num_sockets = int(controller.parse())
- old_num_sockets = len(sockets_list)
- if new_num_sockets > old_num_sockets:
- for i in range(new_num_sockets -
old_num_sockets):
- last_socket =
sockets_list[old_num_sockets + i - 1]
- new_socket = constructor(self,
last_socket.get_cname(), old_num_sockets+i, last_socket.data_type,
vlen=last_socket.vlen)
- sockets_list.append(new_socket)
- elif new_num_sockets < old_num_sockets and
new_num_sockets > 0:#we do not want to remove all sockets
- for i in range(old_num_sockets -
new_num_sockets):
- last_socket =
sockets_list[old_num_sockets - i - 1]
- for connection in
last_socket.get_connections(): connection.disconnect()
-
sockets_list.remove(last_socket)
- self.get_parent().update()
#removing sockets could delete a connection, update all blocks
-
- def _create_labels(self):
- ''' Create the labels for the signal block. '''
- layouts = list()
- # create the main layout #
- layout = gtk.DrawingArea().create_pango_layout(self.cname)
- desc = pango.FontDescription(SIGNAL_BLOCK_FONT)
- layout.set_font_description(desc)
- layouts.append(layout)
- if not self.is_valid(): layout.set_markup('<span
foreground="red"><b>'+self.cname+'</b></span>')
- self.label_width,self.label_height = layout.get_pixel_size()
- # handle each of the displayable params #
- for param in self.displayed_params:
- layout = param.get_layout()
- layouts.append(layout)
- w,h = layout.get_pixel_size()
- self.label_width = max(w, self.label_width)
- self.label_height = self.label_height + h +
LABEL_SEPARATION
- width = self.label_width
- height = self.label_height
- # setup the pixmap #
- pixmap = gtk.gdk.Pixmap(self.get_parent().window, width,
height, -1)
- gc = pixmap.new_gc()
- gc.foreground = self.BG_color
- pixmap.draw_rectangle(gc, True, 0, 0, width, height)
- gc.foreground = self.TXT_color
- # draw the layouts #
- h_off = 0
- for i,layout in enumerate(layouts):
- w,h = layout.get_pixel_size()
- if i == 0: w_off = (width-w)/2
- else: w_off = 0
- pixmap.draw_layout(gc, w_off, h_off, layout)
- h_off = h + h_off + LABEL_SEPARATION
- # create vertical and horizontal images #
- self.horizontal_label = image = pixmap.get_image(0, 0, width,
height)
- if is_vertical(self.get_rotation()):
- self.vertical_label = vimage =
gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
- for i in range(width):
- for j in range(height): vimage.put_pixel(j,
width-i-1, image.get_pixel(i, j))
-
def what_is_selected(self, coor):
""" get the element that is selected, signal block itself or a
socket """
for socket in self.get_sockets():
if socket.what_is_selected(coor) != None:
return socket.what_is_selected(coor)
return Element.what_is_selected(self, coor)
-
- def draw(self, window):
- """ draw the signal block with label and inputs/outputs
"""
- Element.draw(self, window)
- gc = self.gc
- gc.foreground = self.TXT_color
- X,Y = self.get_coordinate()
- if is_horizontal(self.get_rotation()):
- window.draw_image(gc, self.horizontal_label, 0, 0,
X+LABEL_PADDING_WIDTH, Y+(self.H-self.label_height)/2, -1, -1)
- elif is_vertical(self.get_rotation()):
- window.draw_image(gc, self.vertical_label, 0, 0,
X+(self.H-self.label_height)/2, Y+LABEL_PADDING_WIDTH, -1, -1)
- for socket in self.get_sockets(): socket.draw(window)
def get_connections(self):
''' Get a set of all connections from every socket. '''
Modified: grc/branches/gtk_separation/src/Elements/Socket.py
===================================================================
--- grc/branches/gtk_separation/src/Elements/Socket.py 2007-05-18 01:08:54 UTC
(rev 5489)
+++ grc/branches/gtk_separation/src/Elements/Socket.py 2007-05-18 02:34:09 UTC
(rev 5490)
@@ -19,21 +19,15 @@
"""
Elements/Socket.py
Josh Blum
- the graphical input/output sockets of the signal block
+ The elemental input and output sockets of a signal block
"""
-from Elements import *
from Element import Element
-from DataType import *
-from Constants import *
-import Colors
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
+import Utils
+from Connection import TooManyConnectionsException
class Socket(Element):
- """ Socket is a graphical signal block input/output parameter.
+ """ Socket is an input/output element of a signal block.
It has an index, input/output setting, and a data type. """
type = 'socket'
def __init__(self, parent, cname, index, data_type, optional=False,
vlen=None):
@@ -81,75 +75,6 @@
if self.vlen != None and self.vlen.is_valid() and
self.vlen.parse() > 1: return vectorize(self.data_type)
return self.data_type
- def update(self):
- """ update the coloring, a change may have occured in the
block params """
- self.clear()
- self.BG_color = {
- Complex().get_type():Colors.COMPLEX_COLOR,
- Float().get_type():Colors.FLOAT_COLOR,
- Int().get_type():Colors.INT_COLOR,
- Short().get_type():Colors.SHORT_COLOR,
- Byte().get_type():Colors.BYTE_COLOR,
- # and for the vectors #
- ComplexVector().get_type():Colors.COMPLEX_VECTOR_COLOR,
- FloatVector().get_type():Colors.FLOAT_VECTOR_COLOR,
- IntVector().get_type():Colors.INT_VECTOR_COLOR,
- ShortVector().get_type():Colors.SHORT_VECTOR_COLOR,
- ByteVector().get_type():Colors.BYTE_VECTOR_COLOR,
- }[self.get_data_type().get_type()]
- self._create_labels()
- # add the input/output area for each rotation angle
#
- rotation = self.get_rotation()
- conExtLen = CONNECTOR_EXTENSION_LENGTH
- conExtInitLen = CONNECTOR_EXTENSION_INITIAL_LENGTH
- conOff = SOCKET_HEIGHT/2
- index = self.get_index()
- if is_input_socket(self): length =
self.get_parent().get_num_input_sockets()
- elif is_output_socket(self): length =
self.get_parent().get_num_output_sockets()
- offset = (self.get_parent().H - length*SOCKET_HEIGHT -
(length-1)*SOCKET_SEPARATION)/2
- if rotation == 180 or rotation == 270: index = length-index-1
#reverse the order
- if (is_input_socket(self) and rotation == 0) or
(is_output_socket(self) and rotation == 180):
- x = -1*SOCKET_WIDTH
- y = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
- self.add_area((x, y), (SOCKET_WIDTH, SOCKET_HEIGHT))
- if self.is_connected():
self.__set_connector_coordinates((x-1,
y+conOff),(x-conExtInitLen-conExtLen*index, y+conOff))
- elif (is_output_socket(self) and rotation == 0) or
(is_input_socket(self) and rotation == 180):
- x = self.parent.W
- y = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
- self.add_area((x, y), (SOCKET_WIDTH, SOCKET_HEIGHT))
- if self.is_connected():
self.__set_connector_coordinates((x+1+SOCKET_WIDTH,
y+conOff),(x+conExtInitLen+SOCKET_WIDTH+conExtLen*index, y+conOff))
- elif (is_output_socket(self) and rotation == 90) or
(is_input_socket(self) and rotation == 270):
- y = -1*SOCKET_WIDTH
- x = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
- self.add_area((x, y), (SOCKET_HEIGHT, SOCKET_WIDTH))
- if self.is_connected():
self.__set_connector_coordinates((x+conOff, y-1),(x+conOff,
y-conExtInitLen-conExtLen*index))
- elif (is_input_socket(self) and rotation == 90) or
(is_output_socket(self) and rotation == 270):
- y = self.parent.W
- x = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
- self.add_area((x, y), (SOCKET_HEIGHT, SOCKET_WIDTH))
- if self.is_connected():
self.__set_connector_coordinates((x+conOff, y+1+SOCKET_WIDTH),(x+conOff,
y+SOCKET_WIDTH+conExtInitLen+conExtLen*index))
-
- def _create_labels(self):
- ''' Create the labels for the socket. '''
- # create the layout #
- layout = gtk.DrawingArea().create_pango_layout(self.cname)
- desc = pango.FontDescription(SOCKET_FONT)
- layout.set_font_description(desc)
- w,h = self.w,self.h = layout.get_pixel_size()
- # create the pixmap #
- pixmap = gtk.gdk.Pixmap(self.get_parent().get_parent().window,
w, h, -1)
- gc = pixmap.new_gc()
- gc.foreground = self.BG_color
- pixmap.draw_rectangle(gc, True, 0, 0, w, h)
- gc.foreground = self.TXT_color
- pixmap.draw_layout(gc, 0, 0, layout)
- # create the images #
- self.horizontal_label = image = pixmap.get_image(0, 0, w, h)
- if is_vertical(self.get_rotation()):
- self.vertical_label = vimage =
gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), h, w)
- for i in range(w):
- for j in range(h): vimage.put_pixel(j, w-i-1,
image.get_pixel(i, j))
-
def get_index(self):
""" get the index 0, 1, 2... """
return self.index
@@ -158,35 +83,6 @@
""" get the cname """
return self.cname
- def draw(self, window):
- """ draw the paramter with labels """
- Element.draw(self, window)
- gc = self.gc
- gc.foreground = self.TXT_color
- X,Y = self.get_coordinate()
- (x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the
first area's sizes to place the labels
- if is_horizontal(self.get_rotation()): window.draw_image(gc,
self.horizontal_label, 0, 0, x+X+(SOCKET_WIDTH-self.w)/2,
y+Y+(SOCKET_HEIGHT-self.h)/2, -1, -1)
- elif is_vertical(self.get_rotation()): window.draw_image(gc,
self.vertical_label, 0, 0, x+X+(SOCKET_HEIGHT-self.h)/2,
y+Y+(SOCKET_WIDTH-self.w)/2, -1, -1)
-
- def __set_connector_coordinates(self, coor_inner, coor_outer,
rotation=None):
- """ Set the coordinates that connectors may attach to. """
- if rotation == None: rotation = self.get_rotation()
- self.connector_coordinates[rotation] = coor_inner, coor_outer
-
- def get_connector_coordinates(self, rotation=None):
- """ Get the coordinates that Connections may attach to.
"""
- if rotation == None: rotation = self.get_rotation()
- X,Y = self.get_coordinate()
- (x1,y1),(x2,y2)= self.connector_coordinates[rotation]
- return (x1+X, y1+Y), (x2+X, y2+Y)
-
- def get_connector_direction(self):
- """ the direction that the socket points in 0,90,180,270
- this is the rotation degree if the socket is an output or
- the rotation degree + 180 if the socket is an input """
- if is_output_socket(self): return self.get_rotation()
- elif is_input_socket(self): return (self.get_rotation() +
180)%360
-
def is_connected(self):
""" have a Connection (or more)? """
return len(self.connections) > 0
@@ -194,7 +90,7 @@
def connect(self, connection):
""" Add a Connection to this socket,
raise exception if this is an input with an existing
connection. """
- if is_input_socket(self) and self.is_connected(): raise
TooManyConnectionsException()
+ if Utils.is_input_socket(self) and self.is_connected(): raise
TooManyConnectionsException()
self.connections.append(connection)
self.update()
Added: grc/branches/gtk_separation/src/Elements/Utils.py
===================================================================
--- grc/branches/gtk_separation/src/Elements/Utils.py
(rev 0)
+++ grc/branches/gtk_separation/src/Elements/Utils.py 2007-05-18 02:34:09 UTC
(rev 5490)
@@ -0,0 +1,56 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Elements/Utils.py
+ Shared fucntions and exceptions for flow graph elements.
+"""
+
+from SignalBlock import SignalBlock
+from Socket import OutputSocket,InputSocket
+from Connection import Connection
+
+# True if the rotation is 90 or 270 degrees. #
+is_vertical = lambda rot: rot in (90, 270)
+
+# True if the rotation is 0 or 180 degrees. #
+is_horizontal = lambda rot: rot in (0, 180)
+
+def get_angle_from_coordinates((x1,y1), (x2,y2)):
+ """ given two points, calculate the vector direction from point1 to
point2,
+ directions are multiples of 90 degrees. """
+ if y1 == y2:#0 or 180
+ if x2 > x1: return 0
+ else: return 180
+ else:#90 or 270
+ if y2 > y1: return 270
+ else: return 90
+
+##################################################################
+# Test methods for elements
+#################################################################
+# test method for signal blocks #
+is_signal_block = lambda obj: obj!= None and obj.type == SignalBlock.type
+# test methods for sockets #
+is_input_socket = lambda obj: obj!= None and obj.type == InputSocket.type
+is_output_socket = lambda obj: obj!= None and obj.type == OutputSocket.type
+is_socket = lambda obj: is_input_socket(obj) or is_output_socket(obj)
+# test method for connections #
+is_connection = lambda obj: obj!= None and obj.type == Connection.type
+
+
Modified: grc/branches/gtk_separation/src/Elements/__init__.py
===================================================================
--- grc/branches/gtk_separation/src/Elements/__init__.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Elements/__init__.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -21,33 +21,11 @@
All graphical elements used in a flow graph go into this package.
"""
-# True if the rotation is 90 or 270 degrees. #
-is_vertical = lambda rot: rot in (90, 270)
+import Utils
-# True if the rotation is 0 or 180 degrees. #
-is_horizontal = lambda rot: rot in (0, 180)
-
-class InvalidConnectionException(Exception):
- def __str__(self): return 'A connection requires a valid input and
output socket!'
-
-class TooManyConnectionsException(Exception):
- def __str__(self): return 'An input socket may only have one
connection!'
-
-##################################################################
-# Test methods for elements
-#################################################################
-# test method for signal blocks #
-is_signal_block = lambda obj: obj!= None and obj.type == SignalBlock.type
-# test methods for sockets #
-is_input_socket = lambda obj: obj!= None and obj.type == InputSocket.type
-is_output_socket = lambda obj: obj!= None and obj.type == OutputSocket.type
-is_socket = lambda obj: is_input_socket(obj) or is_output_socket(obj)
-# test method for connections #
-is_connection = lambda obj: obj!= None and obj.type == Connection.type
-
-# only import the modules that need external access #
-from Param import Param
-from Socket import OutputSocket,InputSocket
from SignalBlock import SignalBlock
+from Socket import Socket,OutputSocket,InputSocket
from Connection import Connection
+from Element import Element
+from Param import Param
Modified: grc/branches/gtk_separation/src/FlowGraphApp.py
===================================================================
--- grc/branches/gtk_separation/src/FlowGraphApp.py 2007-05-18 01:08:54 UTC
(rev 5489)
+++ grc/branches/gtk_separation/src/FlowGraphApp.py 2007-05-18 02:34:09 UTC
(rev 5490)
@@ -23,6 +23,7 @@
Use a xml input file to build and run a gnu radio flow graph.
"""
+from Elements import SignalBlock
import ParseXML
import Variables
import SignalBlockDefs
@@ -222,7 +223,8 @@
tag = find_data(signal_block, 'tag')
id = find_data(signal_block, 'id')
params = find_data(signal_block, 'params')
- signal_block,runnable_signal_block =
SignalBlockDefs.get_signal_block(None, (0,0), 0, tag, id)
+ sb = SignalBlock(None, (0,0), 0, tag, id)
+ signal_block,runnable_signal_block =
SignalBlockDefs.get_signal_block(sb)
data_type_params = list()
data_type_params.append(self)#put the flow graph thing
here
for i,param in enumerate(params):
Modified: grc/branches/gtk_separation/src/Graphics/ActionHandler.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/ActionHandler.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/ActionHandler.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- ActionHandler.py
+ Graphics/ActionHandler.py
Josh Blum
ActionHandler puts the entire application together by setting up all
the windows
including the flow graph and ActionHandler handles most of the
user inputs.
@@ -28,7 +28,7 @@
import pygtk
pygtk.require('2.0')
import gtk
-import Graphics
+import Windows
from StateCache import StateCache
import ParseXML
import Preferences
@@ -45,7 +45,7 @@
for action in ACTIONS_LIST: action.connect('activate',
self.handle_actions)
self.pid_file = None
### create the main window and setup the Messages ###
- self.main_window = Graphics.MainWindow(self.handle_states)
+ self.main_window = Windows.MainWindow(self.handle_states)
Messages.register_messenger(self.main_window.add_report_line)
Messages.register_messenger(sys.stdout.write)
Messages.send_init()
@@ -138,7 +138,7 @@
if state == APPLICATION_INITIALIZE:
for action in ACTIONS_LIST: action.set_sensitive(False)
#set all actions disabled
# enable a select few actions
- Graphics.enable_usrp_diagnostics() #try to enable
usrp diagnostics
+ Windows.enable_usrp_diagnostics() #try to enable
usrp diagnostics
for action in (APPLICATION_QUIT, FLOW_GRAPH_NEW,
FLOW_GRAPH_OPEN, FLOW_GRAPH_SAVE_AS,
ABOUT_WINDOW_DISPLAY, COLORS_WINDOW_DISPLAY, HOTKEYS_WINDOW_DISPLAY,
FLOW_GRAPH_WINDOW_RESIZE, PREFS_WINDOW_DISPLAY, FLOW_GRAPH_SNAP_SHOT):
@@ -223,18 +223,18 @@
# Window stuff
##############################################################################################
elif state == USRP_DIAGNOSTICS_DISPLAY:
- Graphics.USRPDiagnosticsDialog()
+ Windows.USRPDiagnosticsDialog()
elif state == PREFS_WINDOW_DISPLAY:
- Graphics.PreferencesDialog()
+ Windows.PreferencesDialog()
self.flow_graph.update()
elif state == ABOUT_WINDOW_DISPLAY:
- Graphics.AboutDialog()
+ Windows.AboutDialog()
elif state == COLORS_WINDOW_DISPLAY:
- Graphics.DataTypeColorsDialog()
+ Windows.DataTypeColorsDialog()
elif state == HOTKEYS_WINDOW_DISPLAY:
- Graphics.HotKeysDialog()
+ Windows.HotKeysDialog()
elif state == FLOW_GRAPH_WINDOW_RESIZE:
- dimensions =
Graphics.FlowGraphWindowSizeDialog(self.flow_graph).run()
+ dimensions =
Windows.FlowGraphWindowSizeDialog(self.flow_graph).run()
if dimensions != None:
self.flow_graph.set_size_request(dimensions[0],
dimensions[1])
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
@@ -274,7 +274,7 @@
self.handle_states(APPLICATION_INITIALIZE)
elif state == FLOW_GRAPH_OPEN:
if self.loose_changes():
- fc = Graphics.FlowGraphFileDialog('open',
self.flow_graph_file_path)
+ fc = Windows.FlowGraphFileDialog('open',
self.flow_graph_file_path)
file_path = fc.run()
if file_path != None:
self.flow_graph_file_path = file_path
@@ -289,13 +289,13 @@
Messages.send_fail_save(self.flow_graph_file_path)
self.set_saved_state(False)
elif state == FLOW_GRAPH_SAVE_AS:
- fc = Graphics.FlowGraphFileDialog('save',
self.flow_graph_file_path)
+ fc = Windows.FlowGraphFileDialog('save',
self.flow_graph_file_path)
file_path = fc.run()
if file_path != None:
self.flow_graph_file_path = file_path
self.handle_states(FLOW_GRAPH_SAVE)
elif state == FLOW_GRAPH_SNAP_SHOT:
- fc = Graphics.FlowGraphFileDialog('save image',
self.flow_graph_file_path)
+ fc = Windows.FlowGraphFileDialog('save image',
self.flow_graph_file_path)
file_path = fc.run()
if file_path != None:
pixmap = self.flow_graph.pixmap
@@ -341,7 +341,7 @@
def loose_changes(self):
''' True if the save is disabled or the user says to discard
changes. '''
return not
get_action_from_name(FLOW_GRAPH_SAVE).get_sensitive() or\
- (Graphics.LooseChangesMessage().run())
+ (Windows.LooseChangesMessage().run())
class RUN(Thread):
''' Run the flow graph as a new process and wait on it to finish
'''
Modified: grc/branches/gtk_separation/src/Graphics/Actions.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Actions.py 2007-05-18 01:08:54 UTC
(rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Actions.py 2007-05-18 02:34:09 UTC
(rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Actions.py
+ Graphics/Actions.py
Josh Blum
Global actions for gui elements to communicate state changes to the
action handler.
"""
Modified: grc/branches/gtk_separation/src/Graphics/Colors.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Colors.py 2007-05-18 01:08:54 UTC
(rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Colors.py 2007-05-18 02:34:09 UTC
(rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Colors.py
+ Graphics/Colors.py
Josh Blum
Colors and color-specs used to identify a socket's data type.
"""
Added:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalConnection.py
===================================================================
---
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalConnection.py
(rev 0)
+++
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalConnection.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -0,0 +1,92 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Graphics/GraphicalElements/GraphicalConnection.py
+ Josh Blum
+ The graphical connection for input/output sockets.
+"""
+
+import DataType
+from Elements import Connection,Utils
+from GraphicalElement import GraphicalElement
+from Graphics import Colors
+
+class GraphicalConnection(Connection, GraphicalElement):
+ """ Connection is a graphical connection for sockets """
+ def update(self):
+ """ add the horizontal and vertical lines that will connect
the two parameters """
+ self.clear()
+ input_socket = self.get_input_socket()
+ output_socket = self.get_output_socket()
+ deltaAngle = abs(output_socket.get_connector_direction() -
input_socket.get_connector_direction())
+ (x1, y1) = output_socket.get_connector_coordinates()[1]
+ self.add_line(*output_socket.get_connector_coordinates())
+ (x2, y2) = input_socket.get_connector_coordinates()[1]
+ self.add_line(*input_socket.get_connector_coordinates())
+ if deltaAngle == 180:
+ W = abs(x1 - x2)
+ H = abs(y1 - y2)
+ midX = (x1+x2)/2
+ midY = (y1+y2)/2
+ sW = x1 - x2
+ if output_socket.get_connector_direction() == 0: sW =
sW * -1
+ sH = y1 - y2
+ if output_socket.get_connector_direction() == 270: sH =
sH * -1
+ if ((W>H or sW<0) and
Utils.is_horizontal(output_socket.get_connector_direction())) or\
+ (W>=H and sH>=0 and
Utils.is_vertical(output_socket.get_connector_direction())):
+ self.add_line((x1,y1),(x1,midY))
+ self.add_line((x1,midY),(x2,midY))
+ self.add_line((x2,y2),(x2,midY))
+ elif (H>=W and sW>=0 and
Utils.is_horizontal(output_socket.get_connector_direction())) or\
+ ((H>W or sH<0) and
Utils.is_vertical(output_socket.get_connector_direction())):
+ self.add_line((x1,y1),(midX,y1))
+ self.add_line((midX,y1),(midX,y2))
+ self.add_line((x2,y2),(midX,y2))
+ else:
+ p1 = (x1, y2)
+ p2 = (x2, y1)
+ if Utils.get_angle_from_coordinates((x1,y1),p1) ==
(output_socket.get_connector_direction()+180)%360 or\
+ Utils.get_angle_from_coordinates((x2,y2),p1) ==
(input_socket.get_connector_direction()+180)%360: p = p2
+ else: p = p1
+ self.add_line((x1,y1),p)
+ self.add_line((x2,y2),p)
+
+ def draw(self, window):
+ """ draw the Connection """
+ self.update()
+ GraphicalElement.draw(self, window)
+ gc = self.gc
+ ''' draw error lines around the existing lines when data
types do not match '''
+ if not self.is_valid():
+ gc.foreground = Colors.ERROR_COLOR
+ for (x1, y1),(x2, y2) in
self.lines_dict[self.get_rotation()]:
+ if x1 == x2 and x1 > 0 and x2 > 0: #vertical
+ window.draw_line(gc, x1-1, y1, x2-1, y2)
+ window.draw_line(gc, x1+1, y1, x2+1, y2)
+ elif y1 == y2 and y1 > 0 and y2 > 0: #horizontal
+ window.draw_line(gc, x1, y1-1, x2, y2-1)
+ window.draw_line(gc, x1, y1+1, x2, y2+1)
+
+ def is_valid(self):
+ """ is this connection valid, ie: do the input and output data
types match? """
+ from Graphics import Preferences #preferences
+ return not Preferences.check_connections() or\
+ DataType.can_connect(self.sockets[0].get_data_type(),
self.sockets[1].get_data_type())
+
+
Property changes on:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalConnection.py
___________________________________________________________________
Name: svn:executable
+ *
Added:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalElement.py
===================================================================
---
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalElement.py
(rev 0)
+++
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalElement.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -0,0 +1,62 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Graphics/GraphicalElements/GraphicalElement.py
+ Josh Blum
+ base class for graphical elements such as:
+ signal blocks, input sockets, output sockets and connections
+"""
+from Constants import *
+from Elements import Element
+from Graphics import Colors
+import pygtk
+pygtk.require('2.0')
+import gtk
+import pango
+
+class GraphicalElement(Element):
+ """ Element is the base class for all graphical elements. It
contains an X,Y coordinate, a list
+ of rectangular areas that the element occupies and methods to detect
selection. """
+ def rotate(self, direction):
+ """ rotate all of the areas by 90 degrees, direction is
"left"/"right" """
+ if direction == gtk.DIR_LEFT: delta_rotation = 90
+ elif direction == gtk.DIR_RIGHT: delta_rotation = 270
+ self.set_rotation((self.get_rotation() + delta_rotation)%360)
+ self.update()
+ def draw(self, window, BG_color=Colors.BG_COLOR,
FG_color=Colors.FG_COLOR):
+ """ draw in the given window. """
+ gc = self.get_parent().gc
+ self.gc = gc
+ X,Y = self.get_coordinate()
+ for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
+ aX = X + rX
+ aY = Y + rY
+ gc.foreground = BG_color
+ window.draw_rectangle(gc, True, aX, aY, W, H)
+ if self.is_highlighted(): gc.foreground = Colors.H_COLOR
+ else: gc.foreground = FG_color
+ window.draw_rectangle(gc, False, aX, aY, W, H)
+ for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]:
+ if self.is_highlighted(): gc.foreground = Colors.H_COLOR
+ else: gc.foreground = FG_color
+ window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
+
+
+
+
\ No newline at end of file
Property changes on:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalElement.py
___________________________________________________________________
Name: svn:executable
+ *
Added:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalParam.py
===================================================================
---
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalParam.py
(rev 0)
+++
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalParam.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -0,0 +1,195 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Graphics/GraphicalElements/GraphicalParam.py
+ Josh Blum
+ GTK objects for handling input and the signal block parameter class.
+"""
+
+from Elements import Param
+from DataType import *
+import pygtk
+pygtk.require('2.0')
+import gtk
+import pango
+import gobject
+from Constants import *
+from os import path
+
+######################################################################################################
+# gtk objects for handling input
+######################################################################################################
+
+class InputParam(gtk.HBox):
+ """ The base class for an input parameter inside the input parameters
dialog. """
+ def __init__(self, data_type, handle_changed):
+ gtk.HBox.__init__(self)
+ self.show()
+ self.data_type = data_type
+ self.handle_changed = handle_changed
+ self.label = gtk.Label('') #no label, markup is added by
set_markup
+ self.label.set_size_request(140,30)
+ self.label.show()
+ self.pack_start(self.label, False)
+ self.set_markup = lambda m: self.label.set_markup(m)
+
+class EntryParam(InputParam):
+ """ Provide an entry box for strings and numbers. """
+ def __init__(self, *args):
+ InputParam.__init__(self, *args)
+ self.entry = input = gtk.Entry()
+ input.set_text(self.data_type.get_data())
+ input.connect("changed", self.handle_changed)
+ input.show()
+ self.pack_start(input, False)
+ self.get_text = input.get_text
+
+class FileParam(EntryParam):
+ """ Provide an entry box for filename and a button to browse for a
file. """
+ def __init__(self, *args):
+ EntryParam.__init__(self, *args)
+ input = gtk.Button('...')
+ input.connect('clicked', self.handle_clicked)
+ input.show()
+ self.pack_start(input, False)
+
+ def handle_clicked(self, widget=None):
+ """ If the button was clicked, open a file dialog in open/save
format.
+ Replace the text in the entry with the new filename from the
file dialog. """
+ file_path = self.data_type.parse()
+ # bad file paths will be redirected to default #
+ if not path.exists(path.dirname(file_path)): file_path =
DEFAULT_FILE_PATH
+ if self.data_type.get_type() == FileOpen().get_type():
+ file_dialog = gtk.FileChooserDialog('Open a Data
File...', None,
+ gtk.FILE_CHOOSER_ACTION_OPEN,
('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK))
+ elif self.data_type.get_type() == FileSave().get_type():
+ file_dialog = gtk.FileChooserDialog('Save a Data
File...', None,
+ gtk.FILE_CHOOSER_ACTION_SAVE,
('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK))
+ file_dialog.set_do_overwrite_confirmation(True)
+ file_dialog.set_current_name(path.basename(file_path))
#show the current filename
+ file_dialog.set_current_folder(path.dirname(file_path))
#current directory
+ file_dialog.set_select_multiple(False)
+ file_dialog.set_local_only(True)
+ if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog
+ file_path = file_dialog.get_filename() #get the file
path
+ self.entry.set_text(file_path)
+ self.handle_changed()
+ file_dialog.destroy() #destroy the dialog
+
+class EnumParam(InputParam):
+ """ Provide an entry box for Enum types with a drop down menu. """
+ def __init__(self, *args):
+ InputParam.__init__(self, *args)
+ input = gtk.ComboBox(gtk.ListStore(gobject.TYPE_STRING))
+ cell = gtk.CellRendererText()
+ input.pack_start(cell, True)
+ input.add_attribute(cell, 'text', 0)
+ for cname in self.data_type.get_cnames_list():
input.append_text(cname)
+ input.set_active(int(self.data_type.get_data()))
+ input.show()
+ input.connect("changed", self.handle_changed)
+ self.pack_start(input, False)
+ self.get_text = lambda: str(input.get_active()) #the get text
parses the selected index to a string
+
+######################################################################################################
+# A Parameter, hold a data type and a cname
+######################################################################################################
+
+class GraphicalParam(Param):
+
+ def get_input_object(self):
+ """ Get the graphical gtk class to represent this parameter.
+ Create the input object with this data type and the handle
changed method."""
+ if self.get_data_type().get_base_type() ==
Enum().get_base_type(): input = EnumParam
+ elif self.get_data_type().get_base_type() ==
File().get_base_type(): input = FileParam
+ else: input = EntryParam
+ self.input = input(self.get_data_type(), self.handle_changed)
+ self.handle_changed()
+ return self.input
+
+ def handle_changed(self, widget=None):
+ ''' if the input changed, write the inputs to the param.
'''
+ data_type = self.get_data_type()
+ new_data = self.input.get_text()
+ old_data = data_type.get_data()
+ if old_data != new_data: data_type.set_data(new_data)
+ # Set the markup on the label, red for errors in
cooresponding data type. #
+ cname = self.get_cname()
+ if not data_type.is_valid(): self.input.set_markup('<span
foreground="red"><b>'+cname+'</b></span>')
+ else: self.input.set_markup(cname)
+
+ def get_markup(self):
+ """ Create a markup to display the Param as a label on the
SignalBlock.
+ If the data type is an Enum type, use the cname of the Enum's
current choice.
+ Otherwise, use parsed the data type and use its string
representation.
+ If the data type is not valid, use a red foreground color.
"""
+
###########################################################################
+ # display logic for numbers
+
###########################################################################
+ def float_to_str(var):
+ if var-int(var) == 0: return '%d'%int(var)
+ if var*10-int(var*10) == 0: return '%.1f'%var
+ if var*100-int(var*100) == 0: return '%.2f'%var
+ if var*1000-int(var*1000) == 0: return '%.3f'%var
+ else: return '%.3g'%var
+ def to_str(var):
+ if type(var) == type(str()): return var
+ elif type(var) == type(complex()):
+ if var.imag == var.real == 0: return '0'
#value is zero
+ elif var.imag == 0: return
'%s'%float_to_str(var.real) #value is real
+ elif var.real == 0: return
'%sj'%float_to_str(var.imag) #value is imaginary
+ elif var.imag < 0: return
'%s-%sj'%(float_to_str(var.real), float_to_str(var.imag*-1))
+ else: return '%s+%sj'%(float_to_str(var.real),
float_to_str(var.imag))
+ elif type(var) == type(float()): return
float_to_str(var)
+ elif type(var) == type(int()): return '%d'%var
+ else: return var
+
###########################################################################
+ if self.get_data_type().is_valid():
+ data = self.get_data_type().parse()
+ if self.get_data_type().get_base_type() ==
Enum().get_base_type(): #enum types
+ dt_str = self.get_data_type().get_cname()
+ elif self.get_data_type().get_base_type() ==
File().get_base_type(): #file types
+ suggested_length = 30
+ if len(data) <= suggested_length: dt_str = data
+ else: #truncate the tail if there is not
enough space
+ tail,head = path.split(data)
+ if len(head) >= suggested_length:
dt_str = head
+ else: dt_str =
tail[0:suggested_length-len(head)] + '...' + head
+ elif self.get_data_type().get_base_type() ==
Vector().get_base_type(): #vector types
+ # only keep the first X elements of the
list,
+ X = 4 #display more for non complex vectors
+ dt_str = '[' # replace the
removed elements with a '...'
+ for i,e in enumerate(data):
+ if i < X or i > len(data)-2: #leave
one on the end
+ dt_str = dt_str + to_str(e)
+ if i < len(data)-1 and i+1 !=
X: dt_str = dt_str + ', '
+ elif i == X: dt_str = dt_str + ' ... '
+ dt_str = dt_str + ']'
+ elif self.get_data_type().get_type() ==
Hex().get_type(): dt_str = hex(data) #hex, base 16
+ else: dt_str = to_str(data) #other types
+ return '<b>%s:</b> %s'%(self.cname, dt_str)
+ else: return '<span foreground="red"><b>%s:</b>
error</span>'%self.cname
+
+ def get_layout(self):
+ """ Create a layout based on the current Param's Markup.
"""
+ layout = gtk.DrawingArea().create_pango_layout('')
+ layout.set_markup(self.get_markup())
+ desc = pango.FontDescription(PARAM_FONT)
+ layout.set_font_description(desc)
+ return layout
Property changes on:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalParam.py
___________________________________________________________________
Name: svn:executable
+ *
Added:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSignalBlock.py
===================================================================
---
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSignalBlock.py
(rev 0)
+++
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSignalBlock.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -0,0 +1,165 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Graphics/GraphicalElements/GraphicalSignalBlock.py
+ Josh Blum
+ the graphical signal block
+"""
+
+from Elements import SignalBlock,Utils
+from Graphics import Colors
+from GraphicalParam import GraphicalParam
+from GraphicalElement import GraphicalElement
+from GraphicalSocket import GraphicalInputSocket,GraphicalOutputSocket
+from DataType import *
+from Constants import *
+import pygtk
+pygtk.require('2.0')
+import gtk
+import pango
+
+class GraphicalSignalBlock(SignalBlock, GraphicalElement):
+ """ SignalBlock is a graphical signal block. It is a Element with
an index from the list of
+ possible signal blocks and graphical input/output elements. """
+ param_constructor = GraphicalParam
+ input_socket_constructor = GraphicalInputSocket
+ output_socket_constructor = GraphicalOutputSocket
+ def update(self):
+ """ update the block and parameters and sockets when a change
occurs """
+ self.clear()
+ self._adjust_sockets()
+ self._create_labels()
+ self.W = self.label_width + 2*LABEL_PADDING_WIDTH
+ max_sockets = max(self.get_num_input_sockets(),
self.get_num_output_sockets(), 1)
+ self.H = max(self.label_height+2*LABEL_PADDING_HEIGHT,
2*SOCKET_BORDER_SEPARATION + max_sockets*SOCKET_HEIGHT +
(max_sockets-1)*SOCKET_SEPARATION)
+ if Utils.is_horizontal(self.get_rotation()):
self.add_area((0,0),(self.W,self.H))
+ elif Utils.is_vertical(self.get_rotation()):
self.add_area((0,0),(self.H,self.W))
+ for socket in self.get_sockets(): socket.update()
+
+ def _adjust_sockets(self):
+ ''' Use the input/output socket controllers to adjust the
number of sockets. '''
+ for sockets_list,controller,constructor in
((self.input_sockets, self.input_sockets_controller, GraphicalInputSocket),
+
(self.output_sockets,
self.output_sockets_controller, GraphicalOutputSocket)):
+ if controller != None and controller.is_valid(): #must
be valid before trying to use the value
+ if controller.get_base_type() ==
Vector().get_base_type(): new_num_sockets = len(controller.parse())
+ else: new_num_sockets = int(controller.parse())
+ old_num_sockets = len(sockets_list)
+ if new_num_sockets > old_num_sockets:
+ for i in range(new_num_sockets -
old_num_sockets):
+ last_socket =
sockets_list[old_num_sockets + i - 1]
+ new_socket = constructor(self,
last_socket.get_cname(), old_num_sockets+i, last_socket.data_type,
vlen=last_socket.vlen)
+ sockets_list.append(new_socket)
+ elif new_num_sockets < old_num_sockets and
new_num_sockets > 0:#we do not want to remove all sockets
+ for i in range(old_num_sockets -
new_num_sockets):
+ last_socket =
sockets_list[old_num_sockets - i - 1]
+ for connection in
last_socket.get_connections(): connection.disconnect()
+
sockets_list.remove(last_socket)
+ self.get_parent().update()
#removing sockets could delete a connection, update all blocks
+
+ def _create_labels(self):
+ ''' Create the labels for the signal block. '''
+ layouts = list()
+ # create the main layout #
+ layout = gtk.DrawingArea().create_pango_layout(self.cname)
+ desc = pango.FontDescription(SIGNAL_BLOCK_FONT)
+ layout.set_font_description(desc)
+ layouts.append(layout)
+ if not self.is_valid(): layout.set_markup('<span
foreground="red"><b>'+self.cname+'</b></span>')
+ self.label_width,self.label_height = layout.get_pixel_size()
+ # handle each of the displayable params #
+ for param in self.displayed_params:
+ layout = param.get_layout()
+ layouts.append(layout)
+ w,h = layout.get_pixel_size()
+ self.label_width = max(w, self.label_width)
+ self.label_height = self.label_height + h +
LABEL_SEPARATION
+ width = self.label_width
+ height = self.label_height
+ # setup the pixmap #
+ pixmap = gtk.gdk.Pixmap(self.get_parent().window, width,
height, -1)
+ gc = pixmap.new_gc()
+ gc.foreground = Colors.BG_COLOR
+ pixmap.draw_rectangle(gc, True, 0, 0, width, height)
+ gc.foreground = Colors.TXT_COLOR
+ # draw the layouts #
+ h_off = 0
+ for i,layout in enumerate(layouts):
+ w,h = layout.get_pixel_size()
+ if i == 0: w_off = (width-w)/2
+ else: w_off = 0
+ pixmap.draw_layout(gc, w_off, h_off, layout)
+ h_off = h + h_off + LABEL_SEPARATION
+ # create vertical and horizontal images #
+ self.horizontal_label = image = pixmap.get_image(0, 0, width,
height)
+ if Utils.is_vertical(self.get_rotation()):
+ self.vertical_label = vimage =
gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width)
+ for i in range(width):
+ for j in range(height): vimage.put_pixel(j,
width-i-1, image.get_pixel(i, j))
+
+ def draw(self, window):
+ """ draw the signal block with label and inputs/outputs
"""
+ GraphicalElement.draw(self, window)
+ gc = self.gc
+ gc.foreground = Colors.TXT_COLOR
+ X,Y = self.get_coordinate()
+ if Utils.is_horizontal(self.get_rotation()):
+ window.draw_image(gc, self.horizontal_label, 0, 0,
X+LABEL_PADDING_WIDTH, Y+(self.H-self.label_height)/2, -1, -1)
+ elif Utils.is_vertical(self.get_rotation()):
+ window.draw_image(gc, self.vertical_label, 0, 0,
X+(self.H-self.label_height)/2, Y+LABEL_PADDING_WIDTH, -1, -1)
+ for socket in self.get_sockets(): socket.draw(window)
+
+ def is_valid(self):
+ ''' This block is valid if all the params are valid and all
sockets connected. '''
+ from Graphics import Preferences
+ if Preferences.check_params(): #preferences
+ for param in self.params:
+ if not param.get_data_type().is_valid(): return
False
+ if Preferences.check_sockets(): #preferences
+ for socket in self.get_sockets():
+ if not socket.is_valid(): return False
+ return True
+
+ def modify_type_controller(self, direction):
+ """ If a type controller was set, increment/decrement its index
by 1, use a % to stay in bounds.
+ Direction may be +1 or -1"""
+ if self.type_controller != None and
self.type_controller.get_type() == Enum().get_type():
+ num_choices =
len(self.type_controller.get_cnames_list())
+ index = int(self.type_controller.get_data())
+
self.type_controller.set_data((index+direction+num_choices)%num_choices)
+ self.get_parent().update()
+ return True
+ return False
+
+ def modify_socket_controller(self, direction):
+ """ If a socket controller was set, increment/decrement its
data type by 1, DO NOT go out of bounds.
+ Return True if operation was done. Return False if
operation could not be completed.
+ If there is a controller on input and outputs, show
preference to the output controller.
+ Direction may be +1 or -1. """
+ # Get the socket controller, if there is an input and output
controller, use output #
+ socket_controller = None
+ if self.input_sockets_controller != None: socket_controller =
self.input_sockets_controller
+ elif self.output_sockets_controller != None: socket_controller
= self.output_sockets_controller
+ if socket_controller != None and socket_controller.is_valid()
and socket_controller.get_type() == Int().get_type():
+ old_data = socket_controller.get_data()
+ socket_controller.set_data(socket_controller.parse() +
direction)
+ if socket_controller.is_valid(): #modification was
successful
+ self.get_parent().update()
+ return True
+ else: socket_controller.set_data(old_data)
#restore previous value
+ return False
Property changes on:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSignalBlock.py
___________________________________________________________________
Name: svn:executable
+ *
Added:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSocket.py
===================================================================
---
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSocket.py
(rev 0)
+++
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSocket.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -0,0 +1,144 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Graphics/GraphicalElements/GraphicalSocket.py
+ Josh Blum
+ the graphical input/output sockets of the signal block
+"""
+
+from Elements import Socket,Utils
+from GraphicalElement import GraphicalElement
+from DataType import *
+from Constants import *
+from Graphics import Colors
+import pygtk
+pygtk.require('2.0')
+import gtk
+import pango
+
+class GraphicalSocket(Socket, GraphicalElement):
+ """ Socket is a graphical signal block input/output parameter.
+ It has an index, input/output setting, and a data type. """
+
+ def update(self):
+ """ update the coloring, a change may have occured in the
block params """
+ self.clear()
+ self.BG_color = {
+ Complex().get_type():Colors.COMPLEX_COLOR,
+ Float().get_type():Colors.FLOAT_COLOR,
+ Int().get_type():Colors.INT_COLOR,
+ Short().get_type():Colors.SHORT_COLOR,
+ Byte().get_type():Colors.BYTE_COLOR,
+ # and for the vectors #
+ ComplexVector().get_type():Colors.COMPLEX_VECTOR_COLOR,
+ FloatVector().get_type():Colors.FLOAT_VECTOR_COLOR,
+ IntVector().get_type():Colors.INT_VECTOR_COLOR,
+ ShortVector().get_type():Colors.SHORT_VECTOR_COLOR,
+ ByteVector().get_type():Colors.BYTE_VECTOR_COLOR,
+ }[self.get_data_type().get_type()]
+ self._create_labels()
+ # add the input/output area for each rotation angle
#
+ rotation = self.get_rotation()
+ conExtLen = CONNECTOR_EXTENSION_LENGTH
+ conExtInitLen = CONNECTOR_EXTENSION_INITIAL_LENGTH
+ conOff = SOCKET_HEIGHT/2
+ index = self.get_index()
+ if Utils.is_input_socket(self): length =
self.get_parent().get_num_input_sockets()
+ elif Utils.is_output_socket(self): length =
self.get_parent().get_num_output_sockets()
+ offset = (self.get_parent().H - length*SOCKET_HEIGHT -
(length-1)*SOCKET_SEPARATION)/2
+ if rotation == 180 or rotation == 270: index = length-index-1
#reverse the order
+ if (Utils.is_input_socket(self) and rotation == 0) or
(Utils.is_output_socket(self) and rotation == 180):
+ x = -1*SOCKET_WIDTH
+ y = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
+ self.add_area((x, y), (SOCKET_WIDTH, SOCKET_HEIGHT))
+ if self.is_connected():
self.__set_connector_coordinates((x-1,
y+conOff),(x-conExtInitLen-conExtLen*index, y+conOff))
+ elif (Utils.is_output_socket(self) and rotation == 0) or
(Utils.is_input_socket(self) and rotation == 180):
+ x = self.parent.W
+ y = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
+ self.add_area((x, y), (SOCKET_WIDTH, SOCKET_HEIGHT))
+ if self.is_connected():
self.__set_connector_coordinates((x+1+SOCKET_WIDTH,
y+conOff),(x+conExtInitLen+SOCKET_WIDTH+conExtLen*index, y+conOff))
+ elif (Utils.is_output_socket(self) and rotation == 90) or
(Utils.is_input_socket(self) and rotation == 270):
+ y = -1*SOCKET_WIDTH
+ x = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
+ self.add_area((x, y), (SOCKET_HEIGHT, SOCKET_WIDTH))
+ if self.is_connected():
self.__set_connector_coordinates((x+conOff, y-1),(x+conOff,
y-conExtInitLen-conExtLen*index))
+ elif (Utils.is_input_socket(self) and rotation == 90) or
(Utils.is_output_socket(self) and rotation == 270):
+ y = self.parent.W
+ x = (SOCKET_SEPARATION+SOCKET_HEIGHT)*index+offset
+ self.add_area((x, y), (SOCKET_HEIGHT, SOCKET_WIDTH))
+ if self.is_connected():
self.__set_connector_coordinates((x+conOff, y+1+SOCKET_WIDTH),(x+conOff,
y+SOCKET_WIDTH+conExtInitLen+conExtLen*index))
+
+ def _create_labels(self):
+ ''' Create the labels for the socket. '''
+ # create the layout #
+ layout = gtk.DrawingArea().create_pango_layout(self.cname)
+ desc = pango.FontDescription(SOCKET_FONT)
+ layout.set_font_description(desc)
+ w,h = self.w,self.h = layout.get_pixel_size()
+ # create the pixmap #
+ pixmap = gtk.gdk.Pixmap(self.get_parent().get_parent().window,
w, h, -1)
+ gc = pixmap.new_gc()
+ gc.foreground = self.BG_color
+ pixmap.draw_rectangle(gc, True, 0, 0, w, h)
+ gc.foreground = Colors.TXT_COLOR
+ pixmap.draw_layout(gc, 0, 0, layout)
+ # create the images #
+ self.horizontal_label = image = pixmap.get_image(0, 0, w, h)
+ if Utils.is_vertical(self.get_rotation()):
+ self.vertical_label = vimage =
gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), h, w)
+ for i in range(w):
+ for j in range(h): vimage.put_pixel(j, w-i-1,
image.get_pixel(i, j))
+
+ def draw(self, window):
+ """ draw the paramter with labels """
+ GraphicalElement.draw(self, window, BG_color=self.BG_color)
+ gc = self.gc
+ gc.foreground = Colors.TXT_COLOR
+ X,Y = self.get_coordinate()
+ (x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the
first area's sizes to place the labels
+ if Utils.is_horizontal(self.get_rotation()):
window.draw_image(gc, self.horizontal_label, 0, 0, x+X+(SOCKET_WIDTH-self.w)/2,
y+Y+(SOCKET_HEIGHT-self.h)/2, -1, -1)
+ elif Utils.is_vertical(self.get_rotation()):
window.draw_image(gc, self.vertical_label, 0, 0, x+X+(SOCKET_HEIGHT-self.h)/2,
y+Y+(SOCKET_WIDTH-self.w)/2, -1, -1)
+
+ def __set_connector_coordinates(self, coor_inner, coor_outer,
rotation=None):
+ """ Set the coordinates that connectors may attach to. """
+ if rotation == None: rotation = self.get_rotation()
+ self.connector_coordinates[rotation] = coor_inner, coor_outer
+
+ def get_connector_coordinates(self, rotation=None):
+ """ Get the coordinates that Connections may attach to.
"""
+ if rotation == None: rotation = self.get_rotation()
+ X,Y = self.get_coordinate()
+ (x1,y1),(x2,y2)= self.connector_coordinates[rotation]
+ return (x1+X, y1+Y), (x2+X, y2+Y)
+
+ def get_connector_direction(self):
+ """ the direction that the socket points in 0,90,180,270
+ this is the rotation degree if the socket is an output or
+ the rotation degree + 180 if the socket is an input """
+ if Utils.is_output_socket(self): return self.get_rotation()
+ elif Utils.is_input_socket(self): return (self.get_rotation() +
180)%360
+
+class GraphicalInputSocket(GraphicalSocket):
+ ''' The socket for input '''
+ type = 'input socket'
+
+class GraphicalOutputSocket(GraphicalSocket):
+ ''' The socket for output '''
+ type = 'output socket'
+
\ No newline at end of file
Property changes on:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/GraphicalSocket.py
___________________________________________________________________
Name: svn:executable
+ *
Added: grc/branches/gtk_separation/src/Graphics/GraphicalElements/__init__.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/GraphicalElements/__init__.py
(rev 0)
+++ grc/branches/gtk_separation/src/Graphics/GraphicalElements/__init__.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -0,0 +1,27 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Graphics/GraphicalElements/__init__.py
+ All graphical elements used in a flow graph go into this package.
+"""
+
+from GraphicalSignalBlock import GraphicalSignalBlock
+from GraphicalSocket import GraphicalInputSocket,GraphicalOutputSocket
+from GraphicalConnection import GraphicalConnection
+from GraphicalParam import GraphicalParam
Property changes on:
grc/branches/gtk_separation/src/Graphics/GraphicalElements/__init__.py
___________________________________________________________________
Name: svn:executable
+ *
Modified: grc/branches/gtk_separation/src/Graphics/Messages.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Messages.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Messages.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Messages.py
+ Graphics/Messages.py
Josh Blum
Handle all of the system messages and error reports.
"""
Modified: grc/branches/gtk_separation/src/Graphics/Preferences.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Preferences.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Preferences.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -17,25 +17,25 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Preferences.py
+ Graphics/Preferences.py
Josh Blum
Holds global preferences stored as Params.
"""
from DataType import Bool,FileOpen,Enum,Int
-from Elements import Param
+from Graphics.GraphicalElements import GraphicalParam
import time,socket #for tagging saved files
from Constants import *
import ParseXML
import Messages
-CONNECTION_CHECKING_PREF = Param('Connection Checking', Bool(true='Match Data
Types', false='Ignore Data Types', default=True))
-PARAM_CHECKING_PREF = Param('Parameter Checking', Bool(true='Verify
Parameters', false='Ignore Invalid Params', default=True))
-SOCKET_CHECKING_PREF = Param('Socket Checking', Bool(true='Require
Connections', false='Allow Open Sockets', default=True))
-RESTORE_FLOW_GRAPH_PREF = Param('Restore Flow Graph', Bool(true='Overwrite
Default Flow Graph', false='Keep Default Flow Graph', default=True))
-DEFAULT_FLOW_GRAPH_PREF = Param('Default Flow Graph', FileOpen('',
allow_blank=True))
-SNAP_TO_GRID_PREF = Param('Snap to Grid', Bool(true='On', false='Off',
default=False))
-GRID_SIZE_PREF = Param('Grid Size (pixels)', Enum([
+CONNECTION_CHECKING_PREF = GraphicalParam('Connection Checking',
Bool(true='Match Data Types', false='Ignore Data Types', default=True))
+PARAM_CHECKING_PREF = GraphicalParam('Parameter Checking', Bool(true='Verify
Parameters', false='Ignore Invalid Params', default=True))
+SOCKET_CHECKING_PREF = GraphicalParam('Socket Checking', Bool(true='Require
Connections', false='Allow Open Sockets', default=True))
+RESTORE_FLOW_GRAPH_PREF = GraphicalParam('Restore Flow Graph',
Bool(true='Overwrite Default Flow Graph', false='Keep Default Flow Graph',
default=True))
+DEFAULT_FLOW_GRAPH_PREF = GraphicalParam('Default Flow Graph', FileOpen('',
allow_blank=True))
+SNAP_TO_GRID_PREF = GraphicalParam('Snap to Grid', Bool(true='On',
false='Off', default=False))
+GRID_SIZE_PREF = GraphicalParam('Grid Size (pixels)', Enum([
('10 pixels', 10),
('20 pixels', 20),
('30 pixels', 30),
@@ -46,10 +46,10 @@
('80 pixels', 80),
('90 pixels', 90),
('100 pixels', 100),], 2))
-SHOW_GRID_PREF = Param('Grid Points', Bool(true='Show Grid', false='Hide
Grid', default=False))
-REPORTS_WIN_SHOW_PREF = Param('Reports Window', Bool(true='Show Reports
Window', false='Hide Reports Window', default=True))
-MAIN_WINDOW_WIDTH_PREF = Param('Main Window Width',
Int(DEFAULT_MAIN_WINDOW_WIDTH))
-MAIN_WINDOW_HEIGHT_PREF = Param('Main Window Height',
Int(DEFAULT_MAIN_WINDOW_HEIGHT))
+SHOW_GRID_PREF = GraphicalParam('Grid Points', Bool(true='Show Grid',
false='Hide Grid', default=False))
+REPORTS_WIN_SHOW_PREF = GraphicalParam('Reports Window', Bool(true='Show
Reports Window', false='Hide Reports Window', default=True))
+MAIN_WINDOW_WIDTH_PREF = GraphicalParam('Main Window Width',
Int(DEFAULT_MAIN_WINDOW_WIDTH))
+MAIN_WINDOW_HEIGHT_PREF = GraphicalParam('Main Window Height',
Int(DEFAULT_MAIN_WINDOW_HEIGHT))
###########################################################################
# List of Preferences
Modified: grc/branches/gtk_separation/src/Graphics/StateCache.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/StateCache.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/StateCache.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- StateCache.py
+ Graphics/StateCache.py
Josh Blum
Stores the flow graph states to drive the undo/redo and save interface.
"""
Modified: grc/branches/gtk_separation/src/Graphics/Windows/Bars.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/Bars.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/Bars.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -17,12 +17,12 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/Bars.py
+ Graphics/Windows/Bars.py
Josh Blum
this file will create the GUI's toolbar and menubar
"""
-from Actions import *
+from Graphics.Actions import *
import pygtk
pygtk.require('2.0')
import gtk
Modified: grc/branches/gtk_separation/src/Graphics/Windows/Dialogs.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/Dialogs.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/Dialogs.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -17,19 +17,19 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/Dialogs.py
+ Graphics/Windows/Dialogs.py
Josh Blum
Misc Dialogs
"""
-import Colors
+from Graphics import Colors
import pygtk
pygtk.require('2.0')
import gtk
from DataType import *
from Constants import *
-from Elements import Param
-import Preferences
+from Graphics import Preferences
+from Graphics.GraphicalElements import GraphicalParam
class TextDisplay(gtk.TextView):
""" A non editable gtk text view. """
@@ -90,8 +90,8 @@
self.original_dimensions = width,height =
self.flow_graph.get_size_request() # get the window dimensions
self.width = Int(width, min=MIN_WINDOW_WIDTH,
max=MAX_WINDOW_WIDTH)
self.height = Int(height, min=MIN_WINDOW_HEIGHT,
max=MAX_WINDOW_HEIGHT)
- self.vbox.pack_start(Param('width (pixels)',
self.width).get_input_object(), False)
- self.vbox.pack_start(Param('height (pixels)',
self.height).get_input_object(), False)
+ self.vbox.pack_start(GraphicalParam('width (pixels)',
self.width).get_input_object(), False)
+ self.vbox.pack_start(GraphicalParam('height (pixels)',
self.height).get_input_object(), False)
def run(self):
''' Return the new dimensions rather than a response.
Modified: grc/branches/gtk_separation/src/Graphics/Windows/FlowGraph.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/FlowGraph.py
2007-05-18 01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/FlowGraph.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,15 +17,17 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/FlowGraph.py
+ Graphics/Windows/FlowGraph.py
Josh Blum
flow graph structure for storing signal blocks and their connections
"""
from Constants import *
-from Elements import *
-from Actions import *
-from Colors import BACKGROUND_COLOR, TXT_COLOR
+from Graphics.Actions import *
+from Graphics.Colors import BACKGROUND_COLOR, TXT_COLOR
+from Graphics.GraphicalElements import GraphicalSignalBlock,GraphicalConnection
+from Elements import Utils
+from Elements.Connection import
InvalidConnectionException,TooManyConnectionsException
import pygtk
pygtk.require('2.0')
import gtk
@@ -33,8 +35,9 @@
import SignalBlockDefs
from SignalBlockParamsDialog import SignalBlockParamsDialog
import random
-import Messages
-import Preferences
+from Graphics import Messages
+from Graphics import Preferences
+from Elements import Utils
import ParseXML
class FlowGraph(gtk.DrawingArea):
@@ -81,7 +84,7 @@
index = index + 1
id_found = False
for element in self.elements:
- if is_signal_block(element) and id ==
element.get_id():
+ if Utils.is_signal_block(element) and id ==
element.get_id():
id_found = True
break
if not id_found: #make sure that a
unique id was created
@@ -89,8 +92,9 @@
vAdj =
self.get_parent().get_vadjustment().get_value()
hAdj =
self.get_parent().get_hadjustment().get_value()
x = random.randint(100,400)+int(hAdj)
- y = random.randint(100,400)+int(vAdj)
-
self.elements.append(SignalBlockDefs.get_signal_block(self, (x, y), rot, tag,
id)[0])
+ y = random.randint(100,400)+int(vAdj)
+ sb = GraphicalSignalBlock(self, (x, y), rot,
tag, id)
+
self.elements.append(SignalBlockDefs.get_signal_block(sb)[0])
self.handle_states(SIGNAL_BLOCK_CREATE)
self.update()
return
@@ -98,21 +102,21 @@
def type_controller_modify_selected(self, direction):
""" Change the registered type controller for the selected
signal block.
direction may be +1 or -1 """
- if is_socket(self.selected_element): self.selected_element =
self.selected_element.get_parent()
- if is_signal_block(self.selected_element): return
self.selected_element.modify_type_controller(direction)
+ if Utils.is_socket(self.selected_element):
self.selected_element = self.selected_element.get_parent()
+ if Utils.is_signal_block(self.selected_element): return
self.selected_element.modify_type_controller(direction)
return False
def socket_controller_modify_selected(self, direction):
""" Change socket controller for the selected signal block.
direction may be +1 or -1 """
- if is_socket(self.selected_element): self.selected_element =
self.selected_element.get_parent()
- if is_signal_block(self.selected_element): return
self.selected_element.modify_socket_controller(direction)
+ if Utils.is_socket(self.selected_element):
self.selected_element = self.selected_element.get_parent()
+ if Utils.is_signal_block(self.selected_element): return
self.selected_element.modify_socket_controller(direction)
return False
def param_modify_selected(self):
""" Create and show a param modification dialog for the
selected element (socket and signal block only) """
- if is_socket(self.selected_element): self.selected_element =
self.selected_element.get_parent()
- if is_signal_block(self.selected_element):
+ if Utils.is_socket(self.selected_element):
self.selected_element = self.selected_element.get_parent()
+ if Utils.is_signal_block(self.selected_element):
signal_block_params_dialog =
SignalBlockParamsDialog(self.selected_element)
changed = signal_block_params_dialog.run()
self.update()
@@ -122,12 +126,12 @@
def connect_sockets(self, s1, s2):
""" Connect input and output sockets. Ignore state change
if creation of connection fails. """
try:
- connection = Connection(self, s1, s2)
+ connection = GraphicalConnection(self, s1, s2)
self.elements.append(connection)
self.selected_element = None
self.handle_states(CONNECTION_CREATE)
self.update()
- except Exception, e:
+ except (InvalidConnectionException,
TooManyConnectionsException), e:
Messages.send_fail_connection()
self.handle_states(NOTHING_SELECT)
@@ -141,7 +145,7 @@
def rotate_selected(self, direction):
""" Rotate the selected element by 90 degrees, direction
can be "left"/"right"
True if rotated, otherwise False. Only rotate
SignalBlocks and Sockets. """
- if self.selected_element != None and
(is_signal_block(self.selected_element) or is_socket(self.selected_element)):
+ if self.selected_element != None and
(Utils.is_signal_block(self.selected_element) or
Utils.is_socket(self.selected_element)):
self.selected_element.rotate(direction)
self.draw()
return True
@@ -151,13 +155,13 @@
""" If an element is selected, remove it and its attached
parts from the element list.
True if the element was deleted, otherwise False.
"""
if self.selected_element != None:
- if is_socket(self.selected_element): # found a
socket, set to parent signal block
+ if Utils.is_socket(self.selected_element): # found
a socket, set to parent signal block
self.selected_element =
self.selected_element.get_parent()
- if is_signal_block(self.selected_element): #
delete a signal block
+ if Utils.is_signal_block(self.selected_element):
# delete a signal block
connections =
self.selected_element.get_connections()
for connection in connections:
connection.disconnect()
self.remove_element(self.selected_element)
- elif is_connection(self.selected_element): #
delete a connection
+ elif Utils.is_connection(self.selected_element):
# delete a connection
self.selected_element.disconnect()
self.selected_element = None
self.update()
@@ -197,17 +201,17 @@
old_selection = self.selected_element
self.selected_element = self.what_is_selected((event.x,
event.y))
# handle the state change with the new selection
#
- if is_connection(self.selected_element):
self.handle_states(CONNECTION_SELECT)
- elif is_socket(self.selected_element):
self.handle_states(SOCKET_SELECT)
- elif is_signal_block(self.selected_element):
self.handle_states(SIGNAL_BLOCK_SELECT)
+ if Utils.is_connection(self.selected_element):
self.handle_states(CONNECTION_SELECT)
+ elif Utils.is_socket(self.selected_element):
self.handle_states(SOCKET_SELECT)
+ elif Utils.is_signal_block(self.selected_element):
self.handle_states(SIGNAL_BLOCK_SELECT)
elif self.selected_element == None:
self.handle_states(NOTHING_SELECT)
# this selection and the last were Sockets, try
to connect them #
- if is_socket(old_selection) and
is_socket(self.selected_element) and\
+ if Utils.is_socket(old_selection) and
Utils.is_socket(self.selected_element) and\
old_selection is not self.selected_element:
#cannot be the same socket
self.connect_sockets(old_selection,
self.selected_element)
if self.selected_element != None:
self.selected_element.set_highlighted(True)
# double click detected, bring up params dialog
if possible #
- if event.type == gtk.gdk._2BUTTON_PRESS and
is_signal_block(self.selected_element):
+ if event.type == gtk.gdk._2BUTTON_PRESS and
Utils.is_signal_block(self.selected_element):
self.mouse_pressed = False
self.handle_states(SIGNAL_BLOCK_PARAM_MODIFY)
self.draw()
@@ -315,7 +319,7 @@
self.gc.foreground = TXT_COLOR
self.pixmap.draw_points(self.gc, points)
# draw the foreground #
- for element in filter(is_signal_block, self.elements) +
filter(is_connection, self.elements):
+ for element in filter(Utils.is_signal_block,
self.elements) + filter(Utils.is_connection, self.elements):
element.draw(self.pixmap) # draw signal
blocks first, then connections on the top
if self.mouse_pressed and self.selected_element != None:
self.selected_element.draw(self.pixmap)
@@ -346,7 +350,7 @@
('max', row[3]),
('step', row[4]),
]))
- for element in filter(is_signal_block, self.elements):
+ for element in filter(Utils.is_signal_block, self.elements):
params_list = list()
signal_blocks_list.append(('signal_block', [
('tag', element.get_tag()),
@@ -358,7 +362,7 @@
]))
for param in element.get_params():
params_list.append(('param',
str(param.get_data_type().get_data())) )
- for element in filter(is_connection, self.elements):
+ for element in filter(Utils.is_connection, self.elements):
connections_list.append(('connection', [
('input_signal_block_id',
str(element.get_input_socket().get_parent().get_id())),
('input_socket_index',
str(element.get_input_socket().get_index())),
@@ -401,7 +405,8 @@
rotation = int(find_data(signal_block, 'rotation'))
params = find_data(signal_block, 'params')
try:
- signal_block =
SignalBlockDefs.get_signal_block(self, (x_coordinate,y_coordinate), rotation,
tag, id)[0]
+ sb = GraphicalSignalBlock(self,
(x_coordinate,y_coordinate), rotation, tag, id)
+ signal_block =
SignalBlockDefs.get_signal_block(sb)[0]
for i,param in enumerate(params):
try:
param = find_data([param],
'param')
@@ -418,12 +423,13 @@
output_signal_block_id = find_data(connection,
'output_signal_block_id')
output_socket_index = int(find_data(connection,
'output_socket_index'))
input_socket = output_socket = None
- for element in filter(is_signal_block, self.elements):
+ for element in filter(Utils.is_signal_block,
self.elements):
if element.get_id() == input_signal_block_id:
input_socket = element.get_input_socket(input_socket_index)
if element.get_id() == output_signal_block_id:
output_socket = element.get_output_socket(output_socket_index)
- try: self.elements.append(Connection(self,
input_socket, output_socket))
- except: errors = errors + 'Could not connect "%s"
input[%d] and "%s" output[%d].\n'%(input_signal_block_id, input_socket_index,
-
output_signal_block_id,
output_socket_index)
+ try: self.elements.append(GraphicalConnection(self,
input_socket, output_socket))
+ except (InvalidConnectionException,
TooManyConnectionsException), e:
+ errors = errors + 'Could not connect "%s"
input[%d] and "%s" output[%d].\n'%(
+ input_signal_block_id,
input_socket_index, output_signal_block_id, output_socket_index)
self.selected_element = None
self.update()
return errors
Modified:
grc/branches/gtk_separation/src/Graphics/Windows/FlowGraphFileDialog.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/FlowGraphFileDialog.py
2007-05-18 01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/FlowGraphFileDialog.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/FlowGraphFileDialog.py
+ Graphics/Windows/FlowGraphFileDialog.py
Josh Blum
The open/save dialog for flow graph files and screen shots
"""
Modified: grc/branches/gtk_separation/src/Graphics/Windows/MainWindow.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/MainWindow.py
2007-05-18 01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/MainWindow.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/MainWindow.py
+ Graphics/Windows/MainWindow.py
Josh Blum
The main window, containing all windows, tool bars, and menu bars.
"""
Modified:
grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockParamsDialog.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockParamsDialog.py
2007-05-18 01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockParamsDialog.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/SignalBlockParamsDialog.py
+ Graphics/Windows/SignalBlockParamsDialog.py
Josh Blum
A dialog for editing a signal block's parameters.
"""
Modified:
grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockSelectionWindow.py
===================================================================
---
grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockSelectionWindow.py
2007-05-18 01:08:54 UTC (rev 5489)
+++
grc/branches/gtk_separation/src/Graphics/Windows/SignalBlockSelectionWindow.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/SignalBlockSelectionWindow.py
+ Graphics/Windows/SignalBlockSelectionWindow.py
Josh Blum
The signal block selection window.
Gives the user a tree selection to choose a signal block.
Modified: grc/branches/gtk_separation/src/Graphics/Windows/USRPDiagnostics.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/USRPDiagnostics.py
2007-05-18 01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/USRPDiagnostics.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/USRPDiagnostics.py
+ Graphics/Windows/USRPDiagnostics.py
Josh Blum
A dialog for querying USRP subdevices. USRP interfacing methods
encapsulated here.
"""
@@ -25,10 +25,10 @@
import pygtk
pygtk.require('2.0')
import gtk
-from Actions import USRP_DIAGNOSTICS_DISPLAY,get_action_from_name
-from Elements import Param
+from Graphics.Actions import USRP_DIAGNOSTICS_DISPLAY,get_action_from_name
from DataType import *
from Dialogs import TextDisplay
+from Graphics.GraphicalElements import GraphicalParam
def enable_usrp_diagnostics():
""" Only enable the action for USRP diganostics if gnuradio.usrp
can be imported. """
@@ -51,9 +51,9 @@
('Side B:0', (1, 0)),
('Side A:1', (0, 1)),
('Side B:1', (1, 1)),])
- self.vbox.pack_start(Param('Unit Number',
self.USRP_number).get_input_object(), False)
- self.vbox.pack_start(Param('Transmit/Receive',
self.USRP_type).get_input_object(), False)
- self.vbox.pack_start(Param('Side:Subdevice',
self.USRP_subdev).get_input_object(), False)
+ self.vbox.pack_start(GraphicalParam('Unit Number',
self.USRP_number).get_input_object(), False)
+ self.vbox.pack_start(GraphicalParam('Transmit/Receive',
self.USRP_type).get_input_object(), False)
+ self.vbox.pack_start(GraphicalParam('Side:Subdevice',
self.USRP_subdev).get_input_object(), False)
self.diagnose_button = gtk.Button('Query')
self.diagnose_button.connect('clicked', self.diagnose_usrp)
self.diagnose_button.show()
Modified:
grc/branches/gtk_separation/src/Graphics/Windows/VariableModificationWindow.py
===================================================================
---
grc/branches/gtk_separation/src/Graphics/Windows/VariableModificationWindow.py
2007-05-18 01:08:54 UTC (rev 5489)
+++
grc/branches/gtk_separation/src/Graphics/Windows/VariableModificationWindow.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,14 +17,14 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/VariableModificationWindow.py
+ Graphics/Windows/VariableModificationWindow.py
Josh Blum
The variable modification window.
Allows the user to enter variables and slider information.
"""
from Constants import *
-from Actions import VARIABLE_MODIFY, NOTHING_SELECT
+from Graphics.Actions import VARIABLE_MODIFY, NOTHING_SELECT
import pygtk
pygtk.require('2.0')
import gtk
Modified: grc/branches/gtk_separation/src/Graphics/Windows/__init__.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/Windows/__init__.py
2007-05-18 01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/Graphics/Windows/__init__.py
2007-05-18 02:34:09 UTC (rev 5490)
@@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Graphics/__init__.py
- gtk based classes go into this package
+ Graphics/Windows/__init__.py
+ gtk based window elements go into this package
"""
# only import the modules that need external access #
Added: grc/branches/gtk_separation/src/Graphics/__init__.py
===================================================================
--- grc/branches/gtk_separation/src/Graphics/__init__.py
(rev 0)
+++ grc/branches/gtk_separation/src/Graphics/__init__.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -0,0 +1,23 @@
+"""
+GNU Radio Companion is a graphical interface into the GNU Radio project.
+Copyright (C) 2007 Josh Blum
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+"""
+ Graphics/__init__.py
+ All graphical dependencies used in the gtk application go into this
package.
+"""
+from ActionHandler import ActionHandler
Modified: grc/branches/gtk_separation/src/Run.py
===================================================================
--- grc/branches/gtk_separation/src/Run.py 2007-05-18 01:08:54 UTC (rev
5489)
+++ grc/branches/gtk_separation/src/Run.py 2007-05-18 02:34:09 UTC (rev
5490)
@@ -18,7 +18,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
"""
- Main.py
+ Run.py
Josh Blum
Run the Main GUI. This file must be called by the python interpreter.
"""
@@ -38,7 +38,7 @@
"""%VERSION
parser = OptionParser(usage=usage, version=version)
(options, args) = parser.parse_args()
- from ActionHandler import ActionHandler
+ from Graphics import ActionHandler
if len(args): ActionHandler(args[0])
else: ActionHandler()
Modified: grc/branches/gtk_separation/src/SignalBlockDefs/__init__.py
===================================================================
--- grc/branches/gtk_separation/src/SignalBlockDefs/__init__.py 2007-05-18
01:08:54 UTC (rev 5489)
+++ grc/branches/gtk_separation/src/SignalBlockDefs/__init__.py 2007-05-18
02:34:09 UTC (rev 5490)
@@ -201,9 +201,9 @@
]),
]
-def get_signal_block(parent, coor, rot, lookup_tag, id):
- """ Create a new signal based on a few input parameters. """
- sb = SignalBlock(parent, coor, rot, lookup_tag, id)
+def get_signal_block(sb):
+ """ Load an empty signal block with sockets and parameters based on its
tag. """
+ lookup_tag = sb.get_tag()
for category, signal_blocks in TAGS:
for tag, builder in signal_blocks:
if lookup_tag == tag: return builder(sb)
@@ -215,7 +215,8 @@
tags_to_remove = list()
for tag in tags:
try:
- get_signal_block(None, (0,0), 0, tag[0], '')
+ sb = SignalBlock(None, (0,0), 0, tag[0], '')
+ get_signal_block(sb)
if tag[0] in tags_set: # remove redundant tags
#
print 'Removing redundant tag "%s" in category
"%s"...'%(tag[0], category)
tags_to_remove.append(tag)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r5490 - in grc/branches/gtk_separation: notes src src/Elements src/Graphics src/Graphics/GraphicalElements src/Graphics/Windows src/SignalBlockDefs,
jblum <=