User Module: Page Setup

Share your advanced PureBasic knowledge/code with the community.
collectordave
Addict
Addict
Posts: 1310
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

User Module: Page Setup

Post by collectordave »

In some programmes you need the user to select a target page size for the programme output before invoking the print requester.

Here is a simple module to include in programmes to allow the user to select a page size, orientation and set margins ready for the page to be designed before printing.

I intend the module to be crossplatform and use only Pure Basic commands no API or OS specific features.

If anyone can see any mistakes or can see where the module can be improved please post here. Once I test any code to make sure the basic functionality is not destroyed I will edit this first post with updated code so the latest version is allways available here.

The first thing you need to operate this module is a database of paper sizes here is the code to generate one with a couple of sizes entered.

CreatePaperSizeDB.pb

Code: Select all


UseSQLiteDatabase()

  DBaseID.l
  Define Criteria.s
  
  Criteria = "CREATE TABLE [PaperSize] ([Paper_ID] INTEGER  Not NULL PRIMARY KEY AUTOINCREMENT,[PaperName] VARCHAR(20)  NULL,[PaperHeight] INTEGER  NULL,[PaperWidth] INTEGER  NULL)";

  If CreateFile(0, "PaperSizes.db")
    CloseFile(0)
    DBaseID = OpenDatabase(#PB_Any, "PaperSizes.db", "", "")
    DatabaseUpdate(DBaseID, Criteria)

  
    ;Create records
    Criteria.s = "INSERT INTO PaperSize (PaperName,PaperHeight,PaperWidth) VALUES ('A4',297,210)"
    DatabaseUpdate(DBaseID, Criteria)
    Criteria.s = "INSERT INTO PaperSize (PaperName,PaperHeight,PaperWidth) VALUES ('A5',210,148)"
    DatabaseUpdate(DBaseID, Criteria)
    Criteria.s = "INSERT INTO PaperSize (PaperName,PaperHeight,PaperWidth) VALUES ('A3',420,297)"
    DatabaseUpdate(DBaseID, Criteria)
    Criteria.s = "INSERT INTO PaperSize (PaperName,PaperHeight,PaperWidth) VALUES ('Letter',279,216)"
    DatabaseUpdate(DBaseID, Criteria)
    Criteria.s = "INSERT INTO PaperSize (PaperName,PaperHeight,PaperWidth) VALUES ('Legal',356,216)"
    DatabaseUpdate(DBaseID, Criteria)
  EndIf  

You can of course add more sizes to the database once created. One good thing about using a database of papersizes is that you can restrict the user to using only those paper sizes your programme will support.

Next is the module code

PageSetup.pbi

Code: Select all

DeclareModule PageSetup
  
  ;Anything declared here is available to other modules or main form even after page setup window closure
  Structure Detail
    Title.s
    Height.i
    Width.i
    TopMargin.i
    LeftMargin.i
    BottomMargin.i
    RightMargin.i
    Orientation.i
  EndStructure
  
  Global Pagedetail.Detail
  
  Global Window_ID.l
  
  Global OkPressed.i = #False
  
  ;Procedures needed to open and use Page Setup
  Declare Event_Handler(event)
  Declare Open()
  
EndDeclareModule

Module PageSetup
  EnableExplicit
  
  UseSQLiteDatabase()
  
  ;Page Variables 
  Global PageTitle.s,PageHeight.i,PageWidth.i,TopMargin.i,LeftMargin.i,BottomMargin.i,RightMargin.i,Orientation.i

Global GPageHeight.i,GPageWidth.i
  
  Global btnOk,btnCancel,strTopMargin,strLeftMargin,strBottomMargin,strRightMargin
  Global imgPage,cmb_Printers,cmb_PaperSize,opt_Portrait,opt_Landscape,img_Back.i
  Global PageImage.l,DBID.l

Procedure LoadDefaultPageSizes()
  
  Define Temp.s = ""
  Define Criteria.s
  
  ;Open PageSize Database
  DBID = OpenDatabase(#PB_Any,GetCurrentDirectory() + "PaperSizes.db", "", "") 
  
  ClearGadgetItems(cmb_PaperSize)
  
  Criteria.s = "SELECT * FROM PaperSize; "
  If DatabaseQuery(DBID, Criteria)
    FirstDatabaseRow(DBID)
    temp = GetDatabaseString(DBID,1) + " " + GetDatabaseString(DBID,2) + "mm X " + GetDatabaseString(DBID,3) + "mm"
    AddGadgetItem(cmb_PaperSize, -1, GetDatabaseString(DBID,1))
    While NextDatabaseRow(DBID)
      temp = GetDatabaseString(DBID,1) + " " + GetDatabaseString(DBID,2) + "mm X " + GetDatabaseString(DBID,3) + "mm"
      AddGadgetItem(cmb_PaperSize, -1, GetDatabaseString(DBID,1))
    Wend    
  EndIf
  FinishDatabaseQuery(DBID)
  
  Define iLoop.i

  ;Set user selection or default
  If PageTitle
    SetGadgetText(cmb_PaperSize,PageTitle)
  Else
    SetGadgetText(cmb_PaperSize,"A4")
  EndIf
  
EndProcedure

Procedure GetSelectedPageSize()
  
  Define Criteria.s
  
  Criteria.s = "SELECT * FROM PaperSize WHERE PaperName = '" + GetGadgetText(cmb_PaperSize) + "';"
  If DatabaseQuery(DBID, Criteria)
    If FirstDatabaseRow(DBID) > 0
      PageWidth = GetDatabaseLong(DBID,3)
      PageHeight.i= GetDatabaseLong(DBID,2)
    EndIf
  EndIf
  FinishDatabaseQuery(DBID)
 
EndProcedure

Procedure DrawPageImage()
  
  Define GraphicScale.f
  
  Define Left.i,Top.i
  
  ;Set Orientation
  If Orientation = 0  ;Portrait
    
    GPageHeight = PageHeight
    GPageWidth = PageWidth
       
  ElseIf Orientation = 1
        
    GPageHeight = PageWidth
    GPageWidth = PageHeight
    
  EndIf
      
    ;Calculate Scaling
  If GPageHeight > GPageWidth
    
      GraphicScale = 190/GPageHeight
      
    Else
      
      GraphicScale = 190/GPageWidth
 
    EndIf
    
    ;Create Page Image
    PageImage = CreateImage(#PB_Any,GPageWidth * GraphicScale ,GPageHeight* GraphicScale , 32,RGB(255,255,255))
    
    ;Draw the page image
    If StartDrawing(ImageOutput(PageImage))
         
      ;Add Margin Lines
      FrontColor(RGB(255,0,0)) ; Red lines For Margins
      
      ;Top Margin
      LineXY(0,TopMargin*GraphicScale,190,TopMargin * GraphicScale) 
       
      ;Left Margin
      ;x = PageDetail\LeftMargin
      LineXY(LeftMargin*GraphicScale,0,LeftMargin * GraphicScale, 190)
      
      ;Bottom Margin 
      ;x = PageDetail\BottomMargin
      LineXY(0,(GPageHeight- BottomMargin)*GraphicScale.f,190,(GPageHeight- BottomMargin) * GraphicScale)
      
      ;Right Margin 
      ;x = PageDetail\RightMargin
      LineXY((GPageWidth-RightMargin)*GraphicScale,0,(GPageWidth-RightMargin) * GraphicScale, 190) 
        
      StopDrawing()
        
    EndIf
    
    ;Show Page Image
    SetGadgetState(imgPage,ImageID(PageImage))
    
    ;Centre Page Image 
    If GPageHeight > GPageWidth
      
      left = (190 -GadgetWidth(imgPage))/2
      
    Else
      
     top = (190 -GadgetHeight(imgPage))/2
 
    EndIf
    ResizeGadget(imgPage, left + 330, top + 10, #PB_Ignore, #PB_Ignore) 
    
  EndProcedure

Procedure Open()
  OkPressed = #False  
  Window_ID = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 530, 210, "Page Setup", #PB_Window_TitleBar | #PB_Window_Tool | #PB_Window_ScreenCentered)
  FrameGadget(#PB_Any, 10, 10, 200, 70, " Select Paper Size ")
  btnOk = ButtonGadget(#PB_Any, 10, 165, 100, 30, "Ok")
  btnCancel = ButtonGadget(#PB_Any, 120, 165, 100, 30, "Cancel")
  cmb_PaperSize = ComboBoxGadget(#PB_Any, 20, 40, 180, 20)
  FrameGadget(#PB_Any, 10, 85, 310, 70, " Margins")
  TextGadget(#PB_Any, 20, 105, 50, 20, "Top", #PB_Text_Right)  
  strTopMargin = StringGadget(#PB_Any, 80, 100, 40, 20, Str(PageDetail\TopMargin))
  TextGadget(#PB_Any, 130, 105, 30, 20, "mm")  
  TextGadget(#PB_Any, 170, 105, 50, 20, "Left", #PB_Text_Right)
  strLeftMargin = StringGadget(#PB_Any, 230, 100, 40, 20, Str(PageDetail\LeftMargin)) 
  TextGadget(#PB_Any, 280, 105, 30, 20, "mm")
  TextGadget(#PB_Any, 20, 130, 50, 20, "Bottom", #PB_Text_Right)
  strBottomMargin = StringGadget(#PB_Any, 80, 125, 40, 20, Str(PageDetail\BottomMargin)) 
  TextGadget(#PB_Any, 130, 130, 30, 20, "mm")
  TextGadget(#PB_Any, 170, 130, 50, 20, "Right", #PB_Text_Right)
  strRightMargin = StringGadget(#PB_Any, 230, 125, 40, 20, Str(PageDetail\RightMargin))
  TextGadget(#PB_Any, 280, 130, 30, 20, "mm")

  img_Back = ImageGadget(#PB_Any, 330, 10, 190, 190, 0, #PB_Image_Border)
  imgPage = ImageGadget(#PB_Any, 390, 90, 80, 60, 0)
  opt_Portrait = OptionGadget(#PB_Any, 230, 30, 80, 20, "Portrait")
  opt_Landscape = OptionGadget(#PB_Any, 230, 50, 80, 20, "Landscape")
  FrameGadget(#PB_Any, 220, 10, 100, 70, " Orientation ")
   
  ;Create a black image for background
  SetGadgetState(img_Back,ImageID(CreateImage(#PB_Any,190 ,190 , 32,RGB(0,0,0))))
  
  PageTitle = PageDetail\Title
  Orientation = PageDetail\Orientation
  TopMargin = Pagedetail\TopMargin
  LeftMargin = Pagedetail\LeftMargin
  BottomMargin = Pagedetail\BottomMargin
  RightMargin = Pagedetail\RightMargin
  
  If Orientation = 0 ;Portrait
    SetGadgetState(opt_Portrait,1)
    SetGadgetState(opt_Landscape,0)
  Else
    SetGadgetState(opt_Portrait,0)
    SetGadgetState(opt_Landscape,1)
  EndIf
  
  LoadDefaultPageSizes()
  
  GetSelectedPageSize()
  
  DrawPageImage()
  
  ;Keep PageSetup on top till closed
  StickyWindow(Window_ID, #True) 
  
EndProcedure

Procedure  Event_Handler(Event)
  
  Select Event
         
    Case #PB_Event_Gadget
         
      Select EventGadget()
        
        Case btnOk
          
          Pagedetail\Title = GetGadgetText(cmb_PaperSize)
          Pagedetail\Width = PageWidth
          Pagedetail\Height = PageHeight
          Pagedetail\TopMargin = TopMargin
          Pagedetail\LeftMargin = LeftMargin
          Pagedetail\BottomMargin = BottomMargin
          Pagedetail\RightMargin = RightMargin
          Pagedetail\Orientation = Orientation
          OkPressed = #True
          CloseWindow(Window_ID)
          Window_ID = -1
          
        Case btnCancel
          
          ;Just close the window
          CloseWindow(Window_ID)
          Window_ID = -1 
                       
        Case strTopMargin
          
          TopMargin = Val(GetGadgetText(strTopMargin)) 
          DrawPageImage()  
            
        Case strLeftMargin
          LeftMargin = Val(GetGadgetText(strLeftMargin))
          DrawPageImage()
             
        Case strBottomMargin
          
          BottomMargin = Val(GetGadgetText(strBottomMargin))
          DrawPageImage()
             
        Case strRightMargin
          
          RightMargin = Val(GetGadgetText(strRightMargin))
          DrawPageImage() 

        Case cmb_PaperSize
                       
          ;Get selected page size in mm
          GetSelectedPageSize()  
          DrawPageImage()
             
        Case opt_Portrait
             
          If GetGadgetState(opt_Portrait) = 1
            Orientation = 0
          EndIf
          DrawPageImage()

        Case opt_Landscape
            
          If GetGadgetState(opt_Landscape) = 1
            Orientation = 1
          EndIf
          DrawPageImage()
                       
      EndSelect ; EventGadget()
         
  EndSelect ;Event

EndProcedure

EndModule
And last is a small test\usage programme

frmMain.pb

Code: Select all

EnableExplicit

IncludeFile "PageSetup.pbi"

Global frmMain.i

;Page Variables 
Global PageTitle.s,PageHeight.i,PageWidth.i,TopMargin.i,LeftMargin.i,BottomMargin.i,RightMargin.i,Orientation.i

Global lstPageDetail, btnOk

Define Event.i

Enumeration FormMenu
  #mnuFilePageSetup
EndEnumeration

frmMain = OpenWindow(#PB_Any, 10, 10, 230, 280, "Page Setup Demo", #PB_Window_SystemMenu)
CreateMenu(0, WindowID(frmMain))
MenuTitle("File")
MenuItem(#mnuFilePageSetup, "Page Setup")
lstPageDetail = ListViewGadget(#PB_Any, 10, 10, 210, 180)
btnOk = ButtonGadget(#PB_Any, 30, 210, 100, 30, "Ok")

;Initialise Your Page Variables With Your defaults
PageTitle = "A4"
TopMargin = 15
LeftMargin = 15  
BottomMargin = 15 
RightMargin = 15
Orientation = 0

Procedure Event_Handler(Event)
  
  Select event
    Case #PB_Event_CloseWindow
      End

    Case #PB_Event_Menu
      
      Select EventMenu()
          
        Case #mnuFilePageSetup
          
          ;Set current values here
          PageSetup::Pagedetail\Title = PageTitle
          PageSetup::Pagedetail\TopMargin = TopMargin
          PageSetup::PageDetail\LeftMargin = LeftMargin  
          PageSetup::PageDetail\BottomMargin = BottomMargin  
          PageSetup::PageDetail\RightMargin = RightMargin
          PageSetup::PageDetail\Orientation = Orientation
          PageSetup::Open()
          
      EndSelect ;EventMenu()

    Case #PB_Event_Gadget
      
      Select EventGadget()
          
        Case btnOk
          End
          
      EndSelect ;EventGadget()
      
  EndSelect ;Event

EndProcedure

Repeat
  
  Event = WaitWindowEvent()
  
    Select EventWindow()
      
      Case frmMain
      
        Event_Handler(Event)
      
      Case PageSetup::Window_ID
      
        PageSetup::Event_Handler(Event)
        If PageSetup::OkPressed
          
          ;Store settings for programme use
          PageTitle = PageSetup::Pagedetail\Title
          TopMargin = PageSetup::Pagedetail\TopMargin
          LeftMargin = PageSetup::PageDetail\LeftMargin  
          BottomMargin = PageSetup::PageDetail\BottomMargin
          RightMargin = PageSetup::PageDetail\RightMargin
          Orientation = PageSetup::PageDetail\Orientation
          PageHeight = PageSetup::PageDetail\Height
          PageWidth = PageSetup::PageDetail\Width
          
          ;Display Settings Just for this test programme
          ClearGadgetItems(lstPageDetail)
          AddGadgetItem(lstPageDetail,-1,"Page Title " + PageSetup::PageDetail\Title)
          AddGadgetItem(lstPageDetail,-1,"Page Height " + PageSetup::PageDetail\Height)
          AddGadgetItem(lstPageDetail,-1,"Page Width " + PageSetup::PageDetail\Width)
          AddGadgetItem(lstPageDetail,-1,"Top Margin " + PageSetup::PageDetail\TopMargin)
          AddGadgetItem(lstPageDetail,-1,"Left Margin " + PageSetup::PageDetail\LeftMargin)
          AddGadgetItem(lstPageDetail,-1,"Bottom Margin " + PageSetup::PageDetail\BottomMargin)
          AddGadgetItem(lstPageDetail,-1,"Right Margin " + PageSetup::PageDetail\RightMargin)
          If PageSetup::PageDetail\Orientation = 0
            AddGadgetItem(lstPageDetail,-1,"Orientation  Portrait")
          Else
            AddGadgetItem(lstPageDetail,-1,"Orientation  Landscape")
          EndIf
        EndIf
        
    EndSelect

ForEver  
Enjoy
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
collectordave
Addict
Addict
Posts: 1310
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: User Module: Page Setup

Post by collectordave »

This at the moment has limited usefullness.

It would be great to be able to preselect a printer etc and get page sizes from the printer. I have code for enumerating connected printers on MAC and Windows but my thoughts are that for an application that requires a page setup before printing so pages can be laid out that a simple page sizes database maybe a better way to go.

Another thing I am working on.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
Post Reply