Styling The Timetable View in JavaScript Scheduler

In this blog post we are going to look at the most common adjustments in the appearance of a timetable that developers want to make based on the questions we have received regarding MindFusion Scheduler library for Java Script.

Here is how our timetable will look at the end:

Styling the Timetable View in JS Scheduler

I. General Looks

The overall appearance of the scheduling library is controlled by themes. MindFusion Scheduler comes with a collection of 9 predefined themes. In order to apply a theme you need to:

  • add a reference to the CSS file in the web page where you want the calendar to appear:
      	<link rel="stylesheet" type="text/css" href="themes/gray.css">
  • assign the name of the theme to the theme property of the Calendar class:
    calendar.theme = "gray";
  • Themes can change dramatically the color scheme of the control including the forms that appear for item creation. We recommend that you choose the theme that is most closely related to the colors you want to see and customize it, if necessary.

    Themes in the JavaScript Scheduler

    Each of the themes is in a CSS file and you can search by the color code and replace the occurrences of a given color with another one to fine-tune the color scheme.

    II. Timetable Settings

    Initially, a timetable renders only one day – today. The timetableSettings property, just like the *settings properties for all views supported by the Calendar (—SingleMonth, RespurceView, MonthRange etc.) expose the properties that let you customize the look of the calendar.

    In the case with the timetableView, the number of columns that are rendered depends on the number of dates added to the dates propеrty of timetableSettings In our case we want to show the week, so we add 7 dates:

    //get the current date
    var currDay = schedule.DateTime.today();
    calendar.timetableSettings.dates.clear();
    
    for (var i = 1; i &lt; 8; i++) {
    	calendar.timetableSettings.dates.add(currDay.addDays(-1 * currDay.dayOfWeek + i));	
    	}
    }

    Setting the Number Of Dates in a Timetable in the JavaScript Scheduler

    We also want to scroll week by week. By default the timetable scrolls with one day. In order to scroll more you need to set the scrollStep property to a bigger number:

    calendar.timetableSettings.scrollStep = 7;

    The next thing that we need is to change the time scale. We want the scales to be per 20 minutes and we want to cover the time interval from 10 to 16 o’clock. These is regulated with the startTime and endTime fields of timetableSettings These properties take as an argument the number of minutes. So, if you want your day to start at 8 o’clock your start time needs to be 8×60=480 minutes or you need to assign 480 as value to the startTime property.

    // set the start time to 10:00 AM
    calendar.timetableSettings.  = 600;
    // set the end time to 16:00 PM
    calendar.timetableSettings.endTime = 1020;

    What we want to specify is the format of the header. The default format is based on the locale settings of the user that runs the application. In our application the date in the timetable header renders as DD/MM/YYYY. We will use the titleFormat property. We also use cellTime to change the time scales between each two hours. The default value is 30 minutes. We change it to 20 with the cellTime property.

    calendar.timetableSettings.titleFormat = "d MMMM 
     <b>dddd</b>";
    calendar.timetableSettings.cellTime = schedule.TimeSpan.fromMinutes(20);
    calendar.timetableSettings.cellSize = 20;

    Adjusting the Timetable Settings in the JavaScript Scheduler

    We also increase the cell size – this is the height of rows that are defined by each 20-minute interval. The calendar also shows just one header – that with the dates. We want to render the days header, which shows the day of the week. The property for that is showDayHeader

    calendar.timetableSettings.showDayHeader = true;

    III. CSS Styling

    We’ve customized our timetable as much as we could through the properties and fields of the Calendar control. We would like to add some additional styling, which can be done through css. We use the style inspector of the browser to identify the styles that are applied on the elements that interest us. We would like to show the lines that separate 20 minute cells in yellow and the lines that separate hours in red. Let’s start with the hour lines. The css to render them in red is this one:

    .mfp-timetable-view .mfp-content .mfp-column .mfp-cell-wrap:nth-child(3n+1) .mfp-cell { 
    			border-top: 1px solid red; 
    }

    The class that styles cells is called mfo-cell-wrap. This class regulates the styling for all cells, so we need to apply red border only on the cells that interest us, and they are the 1st, 4th, 9th etc. cell. We want the rest of the cells to be yellow. This is done with the CSS “not” keyword:

    .mfp-timetable-view .mfp-content .mfp-column .mfp-cell-wrap:not(:nth-child(3n+1)) .mfp-cell {  
    			border-top: 1px solid yellow; 
    	}

    This colors the rows of the timetable red/yellow but does not color the delimeters between the time scales. They are regulated by another CSS class and are div elements:

    .mfp-timetable-view.gray .mfp-header-timeline .mfp-group-time div:not(:first-child)
    	{
    
    		border-top: solid 1px yellow;
    	}
    		
    	.mfp-timetable-view.gray .mfp-header-timeline .mfp-hour
    	{
    		border-top: solid 1px red;
    	}

    Note that the CSS style names are with the suffix “gray”. This is the name of the theme. In many cases the class that needs to be changed is bound to a certain theme.

    The last thing that we want to add as styling is a background for the weekend days. We use again the nth-child CSS property. This time the “children” are the 6th and 7th element, so we define styles for them:

    .mfp-timetable-view .mfp-content .mfp-column:nth-child(5n + 6), .mfp-column:nth-child(5n + 7) {
    			background-color: rgba(145, 179, 188, 0.4);
    		}

    We note one more thing. When we create an appointment, the text of the subject is not visible because the line height is too small for the item styling. We have two options: either to increase the cell height, which is set with cellSize and is 20 or to style the item, so that the subject is visible. We choose the latter. We will make the resize line-s smaller because that’s what hiding the subject: the big resize lines:

    .mfp-item-vertical-detail .mfp-subject {
    	flex-shrink: 0 !important;
    }
    
    .mfp-item-vertical-detail .mfp-resize-start,
    .mfp-item-vertical-detail .mfp-resize-end {
    	flex-shrink: 1 !important;
    }

    Here is the final result:

    Styling the Timetable Vew in JS Scheduler

    You can download the sample with all libraries ued and the full source code from this link:

    Styling a Timetable in the JavaScript Scheduler

    You can post technical questions, comments and recommendations about MindFusion Scheduling for JavaScript at the library online forum.

    About Scheduling for JavaScript: MindFusion Js Scheduler is the right solution for all applications that need to render interactive timetables, rich event calendars, lists with appointments or resources. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. The library supports a variety of export options, styling through themes, 6 calendar views and much more. Find out more at https://mindfusion.eu/javascript-scheduler.html

    A Monthly Calendar in Java Swing that Ends at a Given Date

    In this blog post we will build a monthly calendar in Java Swing using the scheduler library. We will use the monthly view of the calendar but we will make it render only 3 months after the current month. By default there are no limits how far users can scroll the months in Single month view both back- and forth-wards. We will let our users scroll as many months they want in the past but only scroll 3 months ahead.

    I. General Settings

    We create an empty project in Eclipse and add the JPlanner.jar as an external Jar library as shows in this picture:

    Then we create a Java class that extends JFrame and there, in the constructor we create a new instance of the Calendar class:

    calendar = new Calendar();
    getContentPane().add(calendar, BorderLayout.CENTER);

    Then we set the current view to be SingleMonth using the setCurrentView method and we set the theme to be silver with setTheme calendar supports a variety ot views and themes, which are members of the CalendarView and ThemeType enumerations.

    II. Handling Events

    We will use the addCalendarListener method to add an instance of the CalendarAdapter class that is used to handle events in the Calendar

    calendar.addCalendarListener(new CalendarAdapter(){		
    		
    		@Override()
    		public void visibleDateChanged(DateChangedEvent e) {
    			onVisibleDateChanged(e);
    		}
    		
    	});

    We will handle the visibleDateChanged event and check when the user is about to scroll to a month that we do not want to show. In our sample we want the user to be able to scroll only three months in advance.

    The Calendar initializes by default with the current date being visible. For a CalendarView this means the current month is rendered. We will keep this date in a global variable for the class because we want to be able to use it in the event handler method:

    protected MainWindow()
    {
    	setDefaultCloseOperation(EXIT_ON_CLOSE);
    	setSize(400, 400);
    	setTitle("Tutorial 1");
    	initialDate = DateTime.now();
    	...........................
    	...........................
    }
    
    private Calendar calendar;
    private DateTime initialDate;

    We will use our initialDate variable to reset the calendar to a data three months after it. Whenever we detect that the user is about to scroll to the 4th month, we reset the date to be 3 months after initialDate’s month. Here is how:

    //make sure that dates are rendered till the end of May
    public void onVisibleDateChanged(DateChangedEvent e)
    {
    					
    	if(e.getNewDate().getMonth() == initialDate.getMonth() + 4)
    	{		
    		calendar.setDate(new DateTime(initialDate.getYear(), 
    				initialDate.getMonth() + 3, initialDate.getDay()));
    	}
    }

    Now if the user want to go to the 4th month, the view will always bring the 3rd month and will not allow switiching to the month ahead.

    With that our tutorial is finished. You can download the sample code from this link:

    Monthly Calendar with Fixed End Date

    Technical support is available at the Java Swing Online Discussion Forum.

    About MindFusion Scheduling for Java Swing: The library provides extensive feature-set for creating and customizing all sorts of calendars, task lists, time-management tables, resource allocation tables and other. It boasts various options for customizing appearance and numerous events for handling user actions. The distribution archive includes a lot of samples and detailed documentation. Learn more at https://mindfusion.eu/java-scheduler.html

    Custom Painting of Resources in Java Scheduler

    In this blog post we will explain how to color cells and resources in the Resource view of the calendar based on a certain criteria. In our case we take the “Resource Table” sample from the Samples for the Java Swing Scheduler and we will edit its code to color the header and background of cells that correspond to given resources, in our sample it is an employee:

    We will also add tooltips that show when the mouse is over cells that correspond to this employee:

    I. General Settings

    The code that we will demonstrate and explain is an extension to the “Resource Table” sample, which you can download from:

    Download Resource Table Java Scheduler Sample

    The sample uses the Scheduling Library for Java Swing, which is included as a Jar reference to the project.

    We create an instance of the Calendar class and set its current time, date and the end date – this is the final date that will be visible in the resource view:

    calendar = new Calendar();
    calendar.setCurrentTime(DateTime.now());
    calendar.setDate(new DateTime(2020, 6, 8));
    calendar.setEndDate(new DateTime(2020, 7, 7));
    

    The Calendar class exposes many methods for customizing the schedule. We first set the view to be CalendarView itemSettings and resourceViewSettings classes provide us with lots of options to customize the calendar look. We use them to twist the appearance of our resource table:

    calendar.getItemSettings().getSelectedItemStyle().setHeaderFont(new Font("Verdana", Font.PLAIN, 9));
    calendar.getItemSettings().getSelectedItemStyle().setHeaderTextAlignment(EnumSet.of(TextAlignment.MiddleLeft));
    calendar.getItemSettings().getSelectedItemStyle().setHeaderTextShadowStyle(ShadowStyle.None);
    ...........................
    ...........................
    calendar.getItemSettings().getStyle().setHeaderFont(new Font("Verdana", Font.PLAIN, 9));
    calendar.getItemSettings().getStyle().setHeaderTextAlignment(EnumSet.of(TextAlignment.MiddleLeft));
    calendar.getItemSettings().getStyle().setHeaderTextShadowStyle(ShadowStyle.None);
    calendar.getItemSettings().getStyle().setHeaderTextShadowOffset(0);
    ...........................
    ...........................
    calendar.getResourceViewSettings().getBottomTimelineSettings().setFormat("EEE (MM/dd)");
    calendar.getResourceViewSettings().getBottomTimelineSettings().setSize(15);
    calendar.getResourceViewSettings().getBottomTimelineSettings().getStyle().setHeaderBrush(Brushes.White);
    calendar.getResourceViewSettings().getBottomTimelineSettings().getStyle().setHeaderFont(new Font("Verdana", Font.BOLD, 10));

    The employees are instances of the Contact class. We add them to the contacts collection of the Calendar, once we’ve created them. It is important that we provide an id to each Contact, because that’s how we will identify them later in code:

    Contact contact = new Contact();
    contact.setFirstName("Mike");
    contact.setId("IdMike");
    contact.setName("Mike");
    calendar.getContacts().add(contact);

    The items that represent tasks for the resources are Appointment instances. We create them in code and add them to the items collection of the Calendar app;

    app = new Appointment();
    app.setStartTime(new DateTime(2006, 3, 27));
    app.setEndTime(new DateTime(2006, 3, 28));
    app.getContacts().add(calendar.getSchedule().getContacts().get("IdMike"));
    app.setHeaderText("21965 Carbon Mesa Rd (1)");
    app.setPriority(0);
    calendar.getSchedule().getItems().add(app);

    The resource view renders rows of cells that correspond to a given Resource, Location, Item, Task etc. The options available are members of the GroupType enumeration. In our sample we group the view by resources e.g. employees:

    calendar.setGroupType(GroupType.GroupByContacts);

    And with that we’ve finished with the general settings and we continue writing the code that will customize our application.

    II. Custom Drawing

    What we want to achieve as appearance of our resource table – selective coloring of the background of cells – can be done through custom drawing. Custom drawing provides us with means to color most elements of the calendar, depending on the view. The “Custom Draw Elements” sample gives us visual representation of the elements that correspond to the CustomDrawElements enumeration, which determines what is to be custom drawn in a schedule:

    The sample is available from this link:

    Java Swing Scheduler: Sample that Demonstrates the Custom Draw Elements according to the Calendar View

    We want to color the resource header and the cells that correspond to this resource. So we use the setCustomDraw method to achieve that:

    calendar.setCustomDraw(EnumSet.of(CustomDrawElements.ResourceViewRowHeader, CustomDrawElements.ResourceViewCellComplete));

    The members of the CustomDrawElements enumeration allow bitwise combining. The drawing is done in an event handler for the draw event:

    calendar.addCalendarListener(new CalendarAdapter() {
    	public void draw(CalendarDrawEvent e) {
    		onCalendarDraw(e);
    	}
    });

    We use a CalendarAdapter to subscribe to the draw event, which we handle with the onCalendarDraw method. The CalendarDrawEvent class exposes many properties that give us information about the element that is being drawn. We use the getElement method to check, which element is being drawn – the cell or the header. If it is the cell, we get the resource that correspond to it and if it is the right one, we paint a rectangle, which represents the whole area of the element that is painted at the moment. We get it with the getBounds method:

    if (e.getElement() == CustomDrawElements.ResourceViewCellComplete)
    {
    	Rectangle bounds = new Rectangle(e.getBounds());
    	bounds.x += 1;
    
    if (e.getResource().getId().equals("IdMike") ||
        e.getResource().getId().equals("IdChuck") ||
        e.getResource().getId().equals("IdTom") ||
        e.getResource().getId().equals("IdAlfredo"))
    				
    {
    	g.fillRectangle(_brush3, bounds);
    	g.drawString("Office", _font, _textBrush, bounds, f);
    }

    We will draw an outline to the resource header that correspond to the same resource, whose rows we colored with _brush3:

    else if (e.getElement() == CustomDrawElements.ResourceViewRowHeader)
    	{
    		if (e.getResource().getId().equals("IdMike") ||
    			e.getResource().getId().equals("IdChuck") ||
    			e.getResource().getId().equals("IdTom") ||
    			e.getResource().getId().equals("IdAlfredo"))
    					
    		{
    			Brush _brush3 = new SolidBrush(new Color(254, 249, 207, 100));
    			g.fillRectangle(_brush3, e.getBounds());
    			g.drawRectangle(new Pen(new Color(163, 198, 134, 255), 2),
    				e.getBounds().getMinX() + 1,
    				e.getBounds().getMinY() + 1,
    				e.getBounds().getMaxX() - 2,
    				e.getBounds().getMaxY() - 2);
    		}
    			
    	}

    Here we check if the custom draw element is CustomDrawElements The CalendarDrawEvent class, which provides data for the event gives us sufficient information to recognize the exact element that is being painted.

    III. Tooltips Over Selected Resources

    By default the Calendar provides tooltips for items. The ItemTooltipEvent provides more information about this. However, we want to show tooltips when the user hovers over cells that correspond to the elements that we’ve painted in section II. We can do that by using a MouseMotionListener and subscribing to the mouseMove event. Note that these are standard Java Swing events:

    calendar.addMouseMotionListener(new MouseAdapter() {
    	public void mouseMoved(MouseEvent e) {
    		onCalendarMouseMoved(e);
         }
    		
    });

    In the event handler method we use the getResourceAt method of the Calendar to learn the resource, over which the mouse is hovering. Then we use the id-s that we’ve assigned to our resources and check if the mouse is over the resources that we want to render tooltips:

    private void onCalendarMouseMoved(MouseEvent e) {
    		
    		Resource res = calendar.getResourceAt(e.getX(), e.getY());
    		
    		if (res.getId().equals("IdMike") ||
    		    res.getId().equals("IdChuck") ||
    		    res.getId().equals("IdTom") ||
    		    res.getId().equals("IdAlfredo"))
    		{				
    			   calendar.setToolTipText(res.getId());				
    				
    		}
    		else
    		{
    		     calendar.setToolTipText("");		    
    		}			
    		
    }

    When we detect that the mouse is over a resource that does not need to render tooltip, we set the tolltip text to be an empty string.

    With that we’ve finished customizing the resource sample. You can download the extended version from this link:

    Resource Table in Java Swing with Tooltips and Resource Coloring: Download

    You are welcome to post your questions and comments at the Online Forum for Scheduling for Java Swing.

    About MindFusion Scheduling for Java Swing: The library provides extensive feature-set for creating and customizing all sorts of calendars, task lists, time-management tables, resource allocation tables and other. It boasts various options for customizing appearance and numerous events for handling user actions. The distribution archive includes a lot of samples and detailed documentation. Learn more at https://mindfusion.eu/java-scheduler.html

    Ski School Scheduler in JavaScript

    In this blog post we will create the following timetable that shows the registered ski classes for a ski school week per week:

    Ski School Scheduler

    We use MindFusion JavaScript Scheduler to create the timetable. We use the BaseForm class to create the custom form that allows us to choose the level of the skier.

    This is not possible in the standard appointment form that comes with the scheduling library.

    I. General Settings

    We need to add a DIV element with an id at the location where we want the timetable to appear on the page. Note that the size of the DIV determines the size of the calendar:

    <div style="position: absolute; width: 100%; height: 97%;">
    
    
    
    <div id="calendar" style="height: 97%; width: 100%;">
    </div>
    
    
    </div>

    MindFusion.Scheduling requires a reference to MindFusion.Scheduling:

    <script src="MindFusion.Scheduling.js" type="text/javascript"></script>
    <script src="SkiSchoolSchedule.js" type="text/javascript"></script>
    <script src="SkiStudentForm.js" type="text/javascript"></script>

    We also add a reference to two JavaScript files that will contain the source code for our application: SkiSchoolSchedule and SkiStudentForm. Finally we add a reference to the CSS file that defines the theme used by the timetable – business.css:

     	<link rel="stylesheet" type="text/css" href="themes/business.css">

    The Scheduling library offers a variety of CSS themes, which you can customize or use as a template to create new ones.

    II. The Timetable

    In the code-behind file we add a mapping to MindFusion.Scheduling namespace and then create the Calendar instance using the id of the DIV element that will render it:

    var p = MindFusion.Scheduling;
    
    // create a new instance of the calendar
    calendar = new p.Calendar(document.getElementById("calendar"));
    
    // set the view to Timetable, which displays the allotment of resources to distinct hours of a day
    calendar.currentView = p.CalendarView.Timetable;
    //set the theme to business as referenced
    calendar.theme = "business";

    We also set the currentView property to CalendarView and specify the theme – business as the name of the CSS file that we referenced.

    The timetableSettings class exposes a dates property where we add the initial dates that will appear in the view:

    //get the current date
    var currDay = p.DateTime.today();
    calendar.timetableSettings.dates.clear();
    
    /* add dates to the timetable in such manner that always a full week
    rom Mo to Su will be visible */
    for(var i = 1; i &lt; 8; i++)
    {
    	calendar.timetableSettings.dates.add(currDay.addDays(-1 * currDay.dayOfWeek + i));
    }

    We get the current date and add in a cycle all 7 days of the week that contains it. We set the scrollStep property to 7, which indicates the number of days that will appear by initial click on one of the navigation arrows in the header:

    // set the number of days to scroll with when a navigation button is clicked
    calendar.timetableSettings.scrollStep = 7;

    We will also use the startTime and endTime properties to indicate the start and and time of the timetable for each day. Those properties show the time as interval added to the start of the current day, in minutes. Thus a startTime value of 300 means the timetable starts 5 hours (5*60 min.) after midnight of the respective day:

    // set the start time to 8:00 AM
    calendar.timetableSettings.startTime = 480;
    // set the end time to 18:00 PM
    calendar.timetableSettings.endTime = 1020;

    III. The Custom Form

    We don’t want to use the standard form for creating appointments. We will create a custom one, you can see the difference between them at this image:

    Ski School Scheduler

    The left one is the custom form while to the right you can see the standard New Appointment form for calendar events.

    The custom form for creating and editing ski lessons derives from the BaseForm class. Here is its constructor:

    var SkiStudentForm = function (calendar, item, type)
    {
            p.BaseForm.call(this, calendar, item);
    
    	this._id = "SkiStudentForm";
    	this._type = type;
    	
    	if(type == "new")
    	this.headerText = "New Skiing Class";
    else
    	this.headerText = "Edit Skiing Class";
    
    	this.levels = [{ value: 0, text: "beginner" }, { value: 1, text: "intermediate" }, { value: 2, text: "advanced" }];
    }

    We want each form to have a reference to the Calendar, to the Item that was created and a type. The type is simply a string and we recognize two types: new and edit e.g. whether we create a new class or edit an existing one.

    Note that in the constructor we initialize a new variable called levels, which will provide data for the combo box with options for the skiing level of the student.

    Then we call the prototype methods of the class and the constructor so we can initialize instances of SkiStudentForm:

    SkiStudentForm.prototype = Object.create(p.BaseForm.prototype);
    SkiStudentForm.prototype.constructor = SkiStudentForm;

    The two methods that are responsible for drawing the contents of a custom BaseForm and its buttons are drawContent and drawButtons

    We start with the drawContent method, where we create the first row:

    SkiStudentForm.prototype.drawContent = function ()
    {
    	p.BaseForm.prototype.drawContent.call(this);
    
    	var content = this.content;
    
    	var row = this.row();
    	row.className = "header-row";
    	row.innerText = "From";
    	content.appendChild(row);
    
    	row = this.row();
    	row.className = "data-row";
    	row.innerHTML = this.item.startTime.toString("dddd, MMMM d,  HH:00", this.formatInfo);
    	content.appendChild(row);
            ........................
    }

    We call the prototype of the drawContent method and we add a new row element. The row is an empty DIV. Then we add another row, this one contains a string. The string represents the start time of the Item .

    We create the combo box using the createDropDownList method. Before we create the combo box we add a new DIV with the label. Then we add another DIV and the dropDownList element to it:

    // create a drop-down list for status
    row = this.row();
    row.className = "header-row";
    row.innerHTML = "Level";
    content.appendChild(row);
    
    var control = this.createDropDownList({ id: "level", items: this.levels, initValue: this.item.tag, addEmptyValue: false });
    control.element.style.width = "200px";
    this.addControl(control);
    
    row = this.row();
    row.className = "input-row";
    row.appendChild(control.element);
    content.appendChild(row);

    The drawButtons method that we implement overrides the buttons of the BaseForm with new ones, styled as we want. Here the code for the Save button:

    // override BaseForm's drawButtons method to create form buttons
    SkiStudentForm.prototype.drawButtons = function ()
    {
           var thisObj = this;
    
    	var btnSave = this.createButton({
    		id: "btnSave",
    		text: "&#x2714;",
    		events: { "click": function click(e)
    		{
    			return thisObj.onSaveButtonClick(e);
    		}
    		}
    	});
    btnSave.element.className = "form-button-save";

    We use the createButton method to create the button, give it an id and assign a text to it. We also indicate the the click event will be handled by an implementation of the default onSaveButtonClick event for BaseForm

    The Cancel button is the same, just the CSS styling for it is different. Both buttons use custom CSS class, which are assigned to them through the className property of HTML Dom elements. Here is the code for the appearance of the two buttons:

    .form-buttons
    {
    	color: #fff;
    	font-size: x-large;
    	text-align: center;
    	margin-top: 20px !important;
    }
    .form-button-save
    {
    	width: 80%;
    	padding: 10px;
    	background-color: #31bd41 !important;
    }
    .form-button-cancel
    {
    	width: 20%;
    	padding: 10px;
    	background-color: #ce0000 !important;
    }

    We create and render an instance of the form with the following lines of code:

    var form = new SkiStudentForm(sender, item, "new");
    form.showForm();

    Here we create the form from an event handler for the Calendar class – we will look at that in the next section.

    IV. Events

    We show the student appointment form when a selection of cells is make. In order to do this we handle the selectionEnd method of the Calendar class:

    // handle the selectionEnd event to show the custom form for item creation
    calendar.selectionEnd.addEventListener(handleSelectionEnd);
    function handleSelectionEnd(sender, args)
    {	
    	/* we create a new item with the selected start and end time
    	var item = new p.Item();
    	item.startTime = args.startTime;
    	item.endTime = args.endTime;	
    	item.tag = 0;	
    
    	// create and show the custom form
    	var form = new SkiStudentForm(sender, item, "new");
    	form.showForm();
    }

    We create a new Item and we set its startTime and endTime to the start and end of the selected cell range. Then we use the current Calendar, which is provided as a sender, the newly created Item and “new” as type to create an instance of the SkiStudentForm and render it.

    What shall we do if we want to use the custom form to edin an existing appointment? We will handle the itemDoubleClick event of the Calendar and show the SkiStudentForm. In this case we will get the Item that we want to edit and provide it as a parameter to the SkiStudentForm instance. We also change the type to be “edit”:

    function handleItemDoubleClick(sender, args)
    {	
    	// show the custom form with data from the clicked item
    	var form = new SkiStudentForm(sender, args.item, "edit");
    	form.showForm();
    }

    These were the most important parts of the ski school scheduler application. The application has a few more, which we did not mention here but you can check them in code. The complete code, together with the themes and libraries used is available at:

    Download the Ski School Scheduler Application

    You can post technical questions, comments and recommendations about MindFusion Scheduling for JavaScript at the library online forum.

    About Scheduling for JavaScript: MindFusion Js Scheduler is the right solution for all applications that need to render interactive timetables, rich event calendars, lists with appointments or resources. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. The library supports a variety of export options, styling through themes, 6 calendar views and much more. Find out more at https://mindfusion.eu/javascript-scheduler.html

    The Different Ways to Style a Schedule

    In this blog post we will look at the different levels of sty‌ling the elements and items of a schedule made with a MindFusion scheduling library. In our sample we use the Java Scheduling Library, but the API members that we use and the cascading levels of styling a schedule are universal across all MindFusion Scheduling components.

    I. Top Level: Theme

    At the top level of styling you have themes. The scheduling library has a set of predefined themes: Light, Lila, Silver, Standard, Vista, Windows2013. You apply one of the predefined themes this way:

    calendar.setTheme(ThemeType.Vista);

    Here is what the calendar looks like styled with the vista theme:

    In JavaScript, the themes are defined in CSS styles and you must reference the desired file and set the name of the theme to the calendar instance. In the other libraries, they are built-in and usually are available as members of an enum.

    You have the option to create a custom theme, which you can save and apply this way:

    calendar.setCustomTheme(new MyTheme());

    Another way to apply the custom theme in Java Scheduling is:

    calendar.setCustomTheme(new MyTheme());

    Here is the look of the calendar with the custom theme:

    The custom theme has changed some of the colors, widened the header so that the week days could be seen and set some borders on the cells.

    Creating a custom Theme requires that you override a strict set of methods. They are the public members of the Theme class. You should override all of them. Among the methods that style the calendar for each view – getMonthRangeSettings getMonthSettings etc. You could override in detail only the method that is responsible for styling the view you would use – if it is only one. For the rest of the methods you could just write:

    private void initialize_MyTheme_ListViewSettings()
    {
    	_listViewSettings = super.createListViewSettings();
    }

    Every method in the Theme class must be dutifully implemented and all settings set. That comes from the fact that a Theme is the last and topmost styling instrument and it must know how to style any element that might not be explicitly styled down the tree.

    The online and offline documentations of the Java Scheduling library come with topics that list in details the styling settings for each of the predefined themes. Our advice is that you get the code of the Theme that looks closest to what you want to have as a structure and modify it.

    The sample project that you can download at the bottom of this post implements a custom Theme based on the Vista theme and lists all members in a theme that you must set with all details.

    II. View and Item Settings

    One level down the tree are the view settings properties. They are available for any view. You can access those settings with the getMonthSettings getMonthRangeSettings etc. methods. Each one of those methods returns the styling settings of a particular view. You should use the one that corresponds to the view you’ve chosen:

    //set the view to SingleMonth
    calendar.setCurrentView(CalendarView.SingleMonth);
    //get the styling settings for SingleMonth view
    calendar.getMonthSettings().getDaySettings().setTodayFillColor(Color.green);

    You can style the items, regardless of the view used, with the ItemSettings object:

    calendar.getItemSettings().setPadding(20);

    The *Settings properties define the appearance of items in terms of alignment, spacing, padding, shadow, date format. The coloring of the elements is left to Style instances. Thus, if you want to change the color of items, you will use:

    //customize just the items through the itemSettings field
    calendar.getItemSettings().setPadding(20);
    		
    Style itemStyle = new Style();
    itemStyle.setBrush(new SolidBrush(Color.white));
    itemStyle.setHeaderTextColor(Color.DARK_GRAY);		
    itemStyle.setHeaderTextShadowStyle(ShadowStyle.None);
    calendar.getItemSettings().setStyle(itemStyle);

    This styles all items on the calendar. For styling a particular item, you should use on of the methods listed underneath.

    Our calendar now has green header on the current day, the background of events is white and there is a bit of a padding added to the events.

    III. Using Events to Style Particular Items

    When you want to select items that you want to style based on some distinct characteristics, you can use events. In our sample we handle the itemCreated event, where we check if the start date of an appointment happens to be during the weekend:

    // Listen for item creation and for draw events
    calendar.addCalendarListener(new CalendarAdapter(){
    	//apply custom styling to selected items
    	public void itemCreated(ItemEvent e) {
    		onItemCreated(e);
    	}				
    });

    The Java Scheduler provides various events, which are accessible through a CalendarListener and CalendarAdapter instances. We handle the itemCreated event this way:

    //color in red events that are scheduled to start on weekends
    protected void onItemCreated(ItemEvent e) {
    
    	Item item = e.getItem();
    	if(item.getStartTime().getDayOfWeek() == DayOfWeek.Saturday || 
    		item.getStartTime().getDayOfWeek() == DayOfWeek.Sunday)
    		{
    			item.getStyle().setBrush(new SolidBrush(new Color(213, 28, 32)));
    			item.getStyle().setHeaderTextColor(Colors.White);
    			item.getPointedStyle().setBrush(new SolidBrush(new Color(100, 100, 100)));
    		}	
    }

    The ItemEvent class provides the item that was created and you can use the instance to apply any particular styling to the item.

    Here is our scheduler, which now colors the items on weekends in red:

    In JavaScript, the items have a special field that allows you to assign to them a custom CSS style that you’ve defined. The style will be applied to the particular item only. The field is called ‘cssClass’.

    IV. Custom Drawing

    When you need to style in a very unique way calendar elements and nothing else helps, you have the option to draw them the way you want. Custom drawing can be made for many parts of the calendar. The available elements are identified as members of the CustomDrawElements enumeration.

    You tell the control that you want to use custom drawing this way:

    //specify that we will use custom drawing	
    calendar.setCustomDraw(EnumSet.of(CustomDrawElements.CellContents));

    The custom drawing must be part of the draw method, which is also a member of CalendarListener:

    // Listen for item creation and for draw events
    calendar.addCalendarListener(new CalendarAdapter(){
    				
    			
    //add custom drawing to CellContents
    @Override()
    public void draw(CalendarDrawEvent e) {
    	onDraw(e);
    	} 
    			
    });

    The event handler method looks like this:

    //apply custom drawing to selected items
    private void onDraw(CalendarDrawEvent e)
    {
    	if (e.getElement() == CustomDrawElements.CellContents)
    	{
    		DateTime date = e.getDate();		
    		
    		//color in light yellow the background of the first 10 days of a month
    		if (date.getDay() &lt; 11)
    		{
    			// Do the custom drawing
    			Rectangle2D bounds = new Rectangle2D.Double(
    			e.getBounds().getX(), e.getBounds().getY(),
    			e.getBounds().getWidth() - 1, e.getBounds().getHeight() - 1);
    			new AwtGraphics(e.getGraphics()).fillRectangle(Brushes.LightYellow, bounds);
    		}
    	}
    }

    The Calendar’s drawEvent class gives us useful methods to learn more about the item that is being drawn. In our case we want to draw the cell contents, so we check if draw was called for the cell contents, and if yes, we get the bounds of the element. We need the check, because draw is called for all elements that support custom drawing and we need to identify which one is drawn at the moment.

    Thanks to the custom drawing, the monthly schedule now has a light yellow background on the first ten days of the month:

    With this our review of the methods to style a schedule is finished. You can download the complete source code of the sample together with all MindFusion libraries used from this link:

    How to Style a Java Schedule: Download Project Source Code

    You can post questions about Mindusion Scheduling components at MindFusion online forums.

    About MindFusion Scheduling Components MindFusion Scheduling components are available for a variety of platforms for web, mobile and desktop programming. All of them include a robust feature set that includes 6 calendar views, predefined themes, various events, predefined forms for creating appointments and recurrence. The components are fully interactive, easy to customize and style and are the ideal choice for any application that needs to implement time management features. You can learn more about MindFusion Scheduling tools at https://mindfusion.eu/scheduling-pack.html.

    Appointment Scheduler in JavaScript

    In this blog post we will build from scratch an appointment schedule for 4 practitioners. Each appointment is logged with the patient name and contact details. Each appointment can be scheduled in one of 4 rooms. We will also implement a check to see if the room that we want to assign to an appointment is free at the particular time.

    You can run the sample online from the link below:

    I. Project Setup

    The first thing we’ll do is to create a DIV element and assign it an id. The JS Schedule library needs and HTML div element where the timetable will be rendered. We create one:

    <div id="calendar" style="height: 100%;width: 100%"></div>

    You can position the div element wherever you wish. It’s location and size determine the location and the size of the schedule.

    Next, we need to reference the Schedule library file. It is called MindFusion.Scheduling. We reference it at the end of the web page, right after the closing BODY tag:

    <script src="scripts/MindFusion.Scheduling.js" type="text/javascript"></script>
    <script src="AppointmentSchedule.js" type="text/javascript"></script>

    We will write the JavaScript code for the appointment schedule in a separate JS file, which we call AppointmentSchedule. We have added a reference to it as well.

    II. Schedule Settings

    In the JavaScript code behind file we first create a mapping to the MindFusion.Scheduling namespace and a reference to the Intellisense file:

    /// <reference path="MindFusion.Scheduling-vsdoc.js">
    
    var p = MindFusion.Scheduling;</reference>

    Next, we use the id of the DIV element to create an instance of the Calendar class:

    // create a new instance of the calendar
    calendar = new p.Calendar(document.getElementById("calendar"));

    We set the currentView property of the calendar to CalendarView Timetable:

    // set the view to Timetable, which displays the allotment 
    // of resources to distinct hours of a day
    calendar.currentView = p.CalendarView.Timetable;

    We use the timetableSettings property to specify the time range for each day. The starttime and endTime properties set exactly the begin and end of the time interval rendered by the timetable columns. They are measured in minutes, from midnight of the day they refer to. We want the schedule to start from 7 A that is why we set 420 as value to the startTime property – the minutes in 7 hours.

    calendar.timetableSettings.startTime = 420;
    calendar.timetableSettings.endTime = 1260;

    The titleFormat property specifies how the date at each timetable column will be rendered. The format string follows the standard date and time pattern for JavaScript:

    calendar.timetableSettings.titleFormat = "dddd d MMM yyyy";
    calendar.itemSettings.tooltipFormat = "%s[hh:mm tt] - %e[hh:mm tt] %h (Contact: %d)";

    The tooltipFormat follows a custom formatting pattern, used by Js Scheduler. It supports special format strings like:

    • %s for start time
    • %e for end time
    • %h for header e.g. the text of the item header
    • %d for description: the text that was assigned as a description of the appointment.

    III. Contacts, Locations and Grouping

    The 4 practitioners are instances of the Contact class:

    resource = new p.Contact();
    resource.firstName = "Dr. Lora";
    resource.lastName = "Patterson";
    resource.tag = 2;
    calendar.schedule.contacts.add(resource);

    It is important to add them to the contacts property of the schedule. The rooms where the appointments take place are Location instances:

    resource.name = "Room 112";
    calendar.schedule.locations.add(resource);

    The grouping of the data that is rendered by the timetable is done is a method called group:

    function group(value) {
    	calendar.contacts.clear();
    	if (value == p.GroupType.GroupByContacts) {
    		// add the contacts by which to group to the calendar.contacts collection
    		calendar.contacts.addRange(calendar.schedule.contacts.items());
    	}
    	calendar.locations.clear();
    	if (value == p.GroupType.GroupByLocations) {
    		// add the locations by which to group to the calendar.locations collection
    		calendar.locations.addRange(calendar.schedule.locations.items());
    	}
    	calendar.groupType = value;
    }

    When we’ve created the locations and contacts, we added them to the locations and contacts collections of the schedule property of the Calendar . Grouping of the appointments is done based on the contacts and locations collections of the Calendar (not the schedule ). That is why in the group method we clear the data from the respective collection and add to it all data from the corresponding collection in the schedule Of course, we must set the groupType property to the appropriate GroupType value.

    IV. Appointments

    When the user selects a range of cells the new Appointment dialog appears automatically. There they can enter all necessary data. We want to implement check if a given room is free when the user tries to create a new appointment in this room. We will do the check in the handler of the itemCreating event. The itemCreating event is raised when the new item has not been ready yet and the ItemModifyingEventArgs object that is provided to the event handler gives the opportunity to cancel the event:

    calendar.itemCreating.addEventListener(handleItemCreating);
    
    function handleItemCreating(sender, args)
    {
    	var appLocation = args.item.location;
    	
    	if(appLocation != null )
    	{
    		if(appLocation.name != "")
    		{
    			var items = calendar.schedule.items.items();
    			for(var i = 0; i &lt; calendar.schedule.items.count(); i++)
    			{
    				if( items[i].location == null)
    					continue;
    				
    				//if the location is the same as the location of another appointment
    				//at that time we cancel the creating of the appointment
    				if( items[i].location.name == appLocation.name &amp;&amp; 
    				overlappingAppointments (args.item, items[i]))
    				{
    					args.cancel = true;
    					alert("The room is already taken");
    				}
    	
    			}
    		}
    	}
    }

    We use a helper method called overlappingAppointments, whose only task is to compare the time range of two items and return true if their time span overlaps – entirely or partially.

    /* checks if the time allotted to two different appointments overlaps */
    function overlappingAppointments(item1, item2)
    {
    	if( item1.startTime &lt; item2.startTime &amp;&amp;
    	    item1.endTime &lt; item2.endTime )
    		  return false;
    		  
    	if( item1.startTime &gt; item2.endTime &amp;&amp;
    	    item1.endTime &gt; item2.endTime )
    		  return false;	
    		  
    		  return true;	  		
    }

    V. Timeline

    Our timetable renders one day at a time. When the user wants to add an appointment that is due in 10 days, they will need to do a lot of scrolling. We can solve the problem by adding a date list at the top o the timetable. The list is another Calendar instance and but its currentView is set to CalendarView List.

    We first need to add another DIV element that will be used by the constructor of the new Calendar:

    <div id="datePicker" style="height: 25px; display: inline-block; margin-bottom: 10px"></div>

    Then we create new Calendar object and make it render a list with dates:

    datePicker = new p.Calendar(document.getElementById("datePicker"));
    datePicker.currentView = p.CalendarView.List;

    By default each Calendar renders the current date when it starts. We make it display a succession of 30 days. We want each day to have a prefix that indicates its week day. In addition, we hide the header of the calendar and stop the default “New Appointment” form from rendering when the user clicks on a cell:

    datePicker.listSettings.visibleCells = datePicker.listSettings.numberOfCells = 30;
    datePicker.listSettings.headerStyle = p.MainHeaderStyle.None;
    datePicker.listSettings.generalFormat = "ddd d";
    datePicker.useForms = false;

    How do we “wire” the selected date in the timeline to the active date in the timetable? We handle the selectionEnd event and there we assign the selected date from the timeline as the active date of the timetable:

    function handleSelectionEnd(sender, args) {
    	var startDate = args.startTime;
    	var endDate = args.endTime;
    
    	// show the selected date range in the timetable
    	calendar.timetableSettings.dates.clear();
    	while (startDate &lt; endDate) {
    		calendar.timetableSettings.dates.add(startDate);
    		startDate = p.DateTime.addDays(startDate, 1);
    	}
    }

    A timetable renders those dates, that are added to its dates property. We add just one date – the date that was selected in the list.

    Let’s not forget to call the render method once we’ve finished all customizations on both Calendar render the calendar control

    calendar.render();
    //render the timeline control
    datePicker.render();

    VI. Styling

    The general styling of the two Calendar instances is done with one of the predefined themes of the Js Scheduler library. First, we need to add a reference to the CSS file, where it is defined. We’ve chosen the “pastel” theme, which is defined in pastel.css:

     	 	<link rel="stylesheet" type="text/css" href="themes/pastel.css">

    Then we need only to set its name as a plain string to the theme property of the two Calendar instances:

    calendar.theme = "pastel";
    datePicker.theme = "pastel";

    There is one more styling that we want to do: we want the appointments of each practicioner to be colored in a different color. We inspect the styling o the appointment element in the browser and find out that the styling of the items is set by the class mfp-item. We create 4 different sub-classes of mfp-item for the 4 practitioners:

    .itemClass0 .mfp-item
    		{
    			background-color: #03738C !important;
    			color: #fff !important;
    		}
    		.itemClass1 .mfp-item
    		{
    			background-color: #03A6A6 !important;
    			color: #fff !important;
    		}
    ..............

    Then we need to assign the correct class to the appointments. We will do this with the cssClass property of Item We handle the itemCreated event where we get information for the appointment that was created:

    calendar.itemCreated.addEventListener(handleItemCreated);
    
    function handleItemCreated(sender, args)
    {
    	var contact = args.item.contacts.items()[0];
    	
    	if(contact != null )
    		args.item.cssClass = "itemClass" + contact.tag;

    }

    The easiest way to assign the correct CSS class to the item is to assign data that will help us generate the correct style name. We use the tag property of Contact and assign each practitioner an id that mirrors the last letter in the CSS class we should assign to the appointments associated with this contact.

    With that our appointment application is finished. You can download the full source code with the libraries and styles used from this link:

    Appointment Schedule in JavaScript: Source Code Download

    About MindFusion JavaScript Scheduler: MindFusion Js Scheduler is the complete solution for all applications that need to render interactive timetables, event schedules or appointment calendars. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. Find out more at https://mindfusion.eu/javascript-scheduler.html

    Binding the Java Planner to Microsoft SQL Server Using JDBC

    In this blog post we will bind to an MS SQL database called bookings. There we will select all data from a table named booking_data. The data is DateTime values. We will use the values to change the background of corresponding calendar cells in a simple Java application. The Java application renders a single-month calendar built with MindFusion Scheduler for Java library.

    I. MS SQL EXPRESS Server Configuration

    We download and install MS SQL EXPRESS server from https://www.microsoft.com/en-us/sql-server/sql-server-downloads. The installation also includes an application called “Sql Server Configuration Manager”. We start that application and click on the “SQL Services” tab. There we need to make sure that two services are running:

    • SQL Server
    • SQL Server Browser

    You start these services by pressing the arrows in the toolbar at the top. If you cannot do this you need to change the Start Mode for this service. Double click it and in the Properties dialog that appears click on the “Service” tab. There you will find the “Start Mode” property and change it to “Manual”. Once you’ve done this you can start, stop or pause the service from the toolbar icons.

    SQL Server Config Manager: Services

    In order to start an SQL Server Service you might have to change its Start Mode to “Manual”.

    Then we click on the “SQL Native Client” node and we select the “Client Protocols” tab. We make sure the TCP/IP Protocol is enabled.

    SQL Server Config Manager: Enable TCP/IP

    Make sure the TCP/IP protocol is enabled for the JDBC connection to succeed

    The next step is to download Microsoft SQL Server Management Studio from https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-2017

    Once we install it and start it we can create a new database called bookings. We right click on the Databases menu and choose “New Database”. We call it “bookings”. Then we expand the tree under “bookings” and right click on the “Tables” node. A window opens where we can define the columns for our new table. We add two columns:

    • id of type integer, which we set at primary key by right-clicking on it.
    • booked_date of type DateTime which will hold the dates that are booked.
    Create a new table using MS SQL Server Management Studio

    MS SQL Server management Studio: the dialog for defining a new table

    After we are done we choose save and at this point we can provide a name for our table. We call it booking_data. With the table defined we right-click on it and choose “Edit Top 200 Rows”. There we add just three days (Jan 16th, Jan 22nd, Jan 26th) all of which in the current month. The data is auto-saved.

    MS SQL Server management Studio: Table Edit

    MS SQL Server Management Studio: here is how you edit the table data

    The next step is to create a new user that will connect to this database. We click the “Security” node on the navigation tree and then “Logins”. Right-click and we choose “New Login”. In the dialog that opens we provide username and password. In order to do that we need to have the Login method set to “SQL Server authentication”. In the next tab “Server Roles” the new user must have “public” role. Then in “User Mapping” we tick the “bookings” database. In the Securables tab in the “Grant” grant column for the user we tick the “Connect SQL” permission. Then we close the dialog.

    Grant SQL Connect to a DB User

    Grant the new user the right to perform an SQL connection.

    We get back to the bookings database and right-click on it. We choose “Properties” and from the dialog we click on the “Permissions” menu. There we select the user we’ve just created and in the Grant column of the underlying table we grant her the “Select” permission.

    Granting User Permissions

    Grant the DB user ‘Select’ permission to perform the required SQL query

    With that the setup of our server and user is ready.

    II. JDBC Driver & MS SQL Express Connection Properties

    We download Microsoft’s JDBC Driver for MS SQL Server from this link: https://docs.microsoft.com/en-us/sql/connect/jdbc/microsoft-jdbc-driver-for-sql-server?view=sql-server-2017 and extract it. Next we create a new Java project. For this project we’ve used IntelliJ IDEA but any other Java IDE will do. In the project tree to the right we create a subfolder that we call “libs”. There we copy the jar of JDBC driver from the folder where we extracted it. Microsoft provides two versions of the driver depending on the JRE that you use. In our case we choose the version for JRE 10, which is called mssql-jdbc-7.0.0.jre10.jar. Next we right-click on the name of our project and select “Open Module Properties”. In the dialog we choose the “Modules” menu and there we click on the “Dependencies” tab and select the mssql-jdbc-7.0.0.jre10.jar module.

    Configuring IntelliJ Project Modules

    Configuring the IntelliJ Project to include the JDBC driver module

    We click on the src folder of the project and add a new class, which we call MainWindow.java. In it we write the method establishConnection. This method is responsible for connecting to the MS SQL database “bookings”. Here is the code that makes the connection:

    private void establishConnection() throws ClassNotFoundException
    {
    
    Connection conn = null;
    PreparedStatement pst;
    
    try {
    // db parameters
    String sql = "SELECT booked_date FROM booking_data";
    
    String userName = "mindfusion";
    String password = "mf123";
    
    String url = "jdbc:sqlserver://DESKTOP-NV9S0TU\\SQLEXPRESS;databaseName=bookings;";
    
    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    conn = DriverManager.getConnection(url, userName, password);
    
    pst = conn.prepareStatement(sql);
    ResultSet rs = pst.executeQuery();
    

    If you’ve followed strictly the steps we’ve outlined so far at this point you would successfully connect to your MS SQL Server with the credentials you’ve set up following the guide so far.

    III. The Schedule Application

    We download MindFusion Java Swing Scheduler from https://mindfusion.eu/java-scheduler.html and unzip it. We copy JPlanner.jar in the libs folder of the project and add it as a project dependency from the “Open Module Settings” menu. Then we define a Calendar variable and assign it to a new instance of the Calendar class.

    public MainWindow() throws ClassNotFoundException
    {
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(368, 362);
    setTitle("MindFusion.Scheduling Sample: Minimal Application");
    
    calendar = new Calendar();
    calendar.setTheme(ThemeType.Light);
    ..................
    ..................
    ..................
    
    establishConnection();
    }
    
    private Calendar calendar;
    

    At the end of the method we call establishConnection and connect to the MS SQL Server.

    IV. Styling the Calendar Dates

    The aim of our sample application shall be to color those cells of the calendar that correspond to the dates we’ve read from the database. In order to do this we use the DateStyle class that sets some useful appearance properties to a range of cells that are specified with the setFrom and setTo methods. We use setBrush to change the background of the cell.

    while (rs.next()) {
    System.out.println(rs.getString("booked_date"));
    Date date = rs.getDate("booked_date");
    
    DateStyle dStyle = new DateStyle();
    dStyle.setFrom(new DateTime(date));
    dStyle.setTo(new DateTime(date));
    Style style = new Style();
    style.setBrush(new SolidBrush(Color.pink));
    dStyle.setStyle(style);
    
    calendar.getDayStyles().add(dStyle);
    
    }
    

    Finally we add the style to the DayStyles collection of the calendar.

    Here is the final application:

    Scheduling application in Java Swing with MS SQL Server JDBC Connection

    MindFusion Java Swing application with the Scheduling library and MS SQL Server

    You can download the project together with the MS SQL Server JDBC driver library and the scheduling library from this link:

    Download JPlanner Sample Application That Uses MS SQL Server JDBC Connection

    About MindFusion Scheduling for Java Swing: The library provides extensive feature-set for creating and customizing all sorts of calendars, task lists, time-management tables, resource allocation tables and other. It boasts various options for customizing appearance and numerous events for handling user actions. The distribution archive includes a lot of samples and extensive documentation. Learn more at https://mindfusion.eu/java-scheduler.html

    Interactive Event Timetable in JavaScript

    This blog post describes the main steps on how to create a schedule table, which shows the allocation of college rooms to different courses. Users can filter the courses by lecturer(s).

    I. Initial Setup

    We start by copying the JavaScript scheduler files that we’ll use in the directory of our project. These are:

    • MindFusion.Scheduling.js – represents the Js Scheduler library
    • MindFusion.Scheduling-vsdoc.js – provides Intellisense support
      standard.css – in a subdirectory “themes”, this is the CSS theme styling of the resource table
    • planner_lic.txt – paste your license key here to disable the trial version label.

    We create then 2 more files specifically for our application:

    • ResourceView.html – the web page of the application
    • ResourceView.js – the JavaScript code that implements the dynamic features of our application.

    II. The HTML Page

    In the head section of our web page we first create a reference to the theme file:

     	 	<link rel="stylesheet" type="text/css" href="themes/standard.css">
    

    At the end of the web page, just before the closing </body> tag we add a reference to the Scheduling.js file that contains the scheduling features and the ResourceView.js files that we’ll write for the application:

    <script src="MindFusion.Scheduling.js" type="text/javascript"></script>
    <script src="ResourceView.js" type="text/javascript"></script>
    

    The calendar library requires an HTML <div> element, which is used to render it. We add one:

    <div id="calendar" style="height: 100%; width: 100%;"></div>

    It is important that you add an id to this <div> because we need to reference it in the JS code behind file.

    III. Basic JavaScript Settings

    At the top of the JavaScript code-behind file we add a reference to the Intellisense file. We also create a mapping to MindFusion.Scheduling namespace:

    /// <reference path="MindFusion.Scheduling-vsdoc.js"></reference>
    var p = MindFusion.Scheduling
    

    Then we create the calendar object. We need a reference to the <div> element that will render it:

    // create a new instance of the calendar
    calendar = new p.Calendar(document.getElementById("calendar"));
    

    For this sample we will use the ResourceView The currentView property specifies that. In addition, we set the count of visible cells in the calendar to 7. That is done through the resourceViewSettings property of the calendar

    // set the view to ResourceView, which displays the distribution of resources over a period of time
    calendar.currentView = p.CalendarView.ResourceView;
    
    // set the number of visible cells to 7
    calendar.resourceViewSettings.visibleCells = 7;
    

    The itemSettings proeprty lets us customize the items in the schedule We use titleFormat and tooltipFormat to specify how the title and tooltip of each item will be rendered. Both properties use special format strings:

    • %s – the start date will be rendered
    • %e – the end date of the item will be rendered
    • %d – the details of the item will be rendered.

    You can specify the way dates and time are formatted by adding the desired format in brackets:

    // show hours on items
    calendar.itemSettings.titleFormat = "%s[HH:mm] - %e[HH:mm] %h";
    calendar.itemSettings.tooltipFormat = "%d";
    

    Then we set the theme of the calendar to standard, whose css file we referenced in the web page:

    calendar.theme = "standard";

    and we make one more adjustment – the name of contacts will be taken from the last name of the person. Possible valies are “F”, “M” and “L” – for first, middle and last name.

    calendar.contactNameFormat = "L";

    IV. Resources

    When the calendar initially loads there are several contacts and locations available. The objects that represent them are instances of the Contact and Location classes. After we create them we add them to the contacts and locations collections of the calendar schedule.

    var resource;
    
    // Add professor names to the schedule.contacts collection.
    resource = new p.Contact();
    resource.firstName = "Prof. William";
    resource.lastName = "Dyer";
    calendar.schedule.contacts.add(resource);
    
    resource = new p.Location();
    resource.name = "Room D";
    calendar.schedule.locations.add(resource);
    

    Now, when the user creates a new course they will see the Contact and Location in the Options pane of the “Create Item” form:

    V. Items

    The items are instances of the Item class. They represent the classes of the different lecturers. We use the startTime and endTime properties of Item to specify when the class takes place. The subject property gives the name of the class:

    //always start with the current date
    var date = p.DateTime.today();
    
    item = new p.Item();
    item.startTime = p.DateTime.addHours(date.addDays(1), 14);
    item.endTime = p.DateTime.addHours(item.startTime, 1);
    item.subject = "Classical Mechanics";
    

    We use the location and contacts properties to set where the lecture takes place and who teaches it. Note that the contacts property is of type collection and we can assign several lecturers to one class:

    item.location = calendar.schedule.locations.items()[0];
    item.contacts.add(calendar.schedule.contacts.items()[0]);
    

    We get the location and the contact from the schedule’s lists with locations and contacts We must also set the details of the item – they will be rendered as a tooltip, if you remember. We want the tooltip to show the two names of the lecturer and the location. Here is how we must define it:

    item.details = item.contacts.items()[0].firstName + " " +
    item.contacts.items()[0].lastName + " - " + item.location.name;
    

    We must add the item to the items collection of the schedule we render the calendar render the calendar

    calendar.render();
    

    VI. Events

    When users create new items we must set their details to tell the name and the location of the new class. We handle the itemCreating event to do this:

    // attach handler - creating an item
    calendar.itemCreating.addEventListener(handleItemCreating); 
    
    function handleItemCreating(sender, args) {
        handleItemModified(sender, args);
        if (args.item.contacts.count() &gt; 0) {
            //the details field is used by the tooltip
            args.item.details = args.item.contacts.items()[0].firstName + " " +
                    args.item.contacts.items()[0].lastName;
    
            if (args.item.location != null)
                args.item.details += " - " + args.item.location.name;
        }
    
    }
    

    The itemCreating event provides an instance of the ItemModifyingEventArgs class as a second argument to the handler method. There we use the item property that tells us which item is being modified. We then take the desired contact and Location information from the contacts and location properties of the item.

    When a new course item is dragged to another location we must change its color accordingly. We do this by handling the itemModified event.

    // attach handler - modifying an item
    calendar.itemModified.addEventListener(handleItemModified);
    

    The diferent background color of the items is achieved by custom CSS classes. We use the cssClass property of the Item class. The CSS styles are defined in the <HEAD> section of the web page:

     .mfp-planner.standard .itemClass1 .mfp-item {
                background-color: 	#0c71af;
            }
    
    .mfp-planner.standard .itemClass2 .mfp-item {
                background-color: #f81e1e;
            }
    ...........
    

    The handler method checks the new location and assigns the appropriate CSS style:

    function handleItemModified(sender, args)
    {
        // you don't have to check any other conditions like dragging to another room, 
        // as it will stay the same color if you make other changes (other than dragging to a different room)
        if (args.item != null){
            switch (args.item.location.name) {
                case "Room A":  //we can also implement it with for
                    args.item.cssClass = 'itemClass1';
                    console.log("a");
                    break;
                case "Room B":
                    args.item.cssClass = 'itemClass2';
                    break;
                case "Room C":
                    args.item.cssClass = 'itemClass3';
                    break;
                case "Room D":
                    args.item.cssClass = 'itemClass1';
                    break;
                case "Room E":
                    args.item.cssClass = 'itemClass2';
                    break;
                case "Room F":
                    args.item.cssClass = 'itemClass3';
                    break;
                default:
                    args.item.cssClass = 'itemClass1';
            }
        }
    }
    

    The item property of the args parameter of the handler method provides access to the item that was modified.

    VII. Filtering Professors

    We want to add one last feature to our application. We want the user to be able to render courses only by a given professor.

    We first add checkboxes with the names of the lecturers. Each checkbox has the same handler method for the click event:

    <input id="dyer" checked="checked" name="subscribe" type="checkbox" value="Dyer>
    <label for=">Prof. William Dyer
    
    <input id="fletcher" checked="checked" name="subscribe" type="checkbox" value="Fletcher">
    <label for="fletcher">Prof. Ann Fletcher</label>
    ...........................
    

    The handler method needs to look at two cases. The first case is when the class is taught by a single professor. In this case we cycle through all items and make the item visible or not depending on whether the check box with the name of the professor is checked:

    // if there is at least one present professor from the lecture professors, the lecture will not disappear
    function handleClick(cb) {
    for (var i = 0; i &lt; calendar.schedule.items.count(); i++) {
            var item = calendar.schedule.items.items()[i]; //we iterate through every element
            if (item.contacts.count() == 1) {
                if (item.contacts.items()[0].lastName == cb.value)
                    item.visible = cb.checked;
            }
          }
    .......................
    }
    

    In the second case we look at courses that are taught by more than one lecturer. In this case we show the item if the checkbox with the name of at least one of the lecturers is selected:

    else if (item.contacts.count() &gt; 1) {
    for (var j = 0; j &lt; item.contacts.count() ; j++) {
                    if (item.contacts.items()[j].lastName == cb.value) { // the checked/unchecked professor is in the contacts of this item
                        if (cb.checked == true) item.visible = true; // if there is a check, the item must be visible
                        else { // if there is no check, we see if there is at least one professor in the list of contacts of the item
                            item.visible = professorPresent(item);
                        }
    
                    }
                }
            }
    

    Finally we repaint the calendar:

    // repaint the calendar
    this.calendar.repaint(true);
    

    Here the professorPresent method checks if at least one of the check boxes with professors that are present as lecturers in the item that we provide as argument are selected:

    // return true if even 1 professor from the item's contacts is present, false otherwise
    function professorPresent(item) {
        console.log(item.contacts.count());
        for (var j = 0; j &lt; item.contacts.count() ; j++) {
            var checkBoxId = item.contacts.items()[j].lastName.toLowerCase();
            var checkBox = document.getElementById(checkBoxId);
            if (checkBox!= null &amp;&amp; checkBox.checked == true) {
                return true;
            }
        }
        return false;
    }
    

    And that’s the end of this blog post. Here is a link to download the complete source code of this application:

    Download The Sample Resource View Application

    About MindFusion JavaScript Scheduler: MindFusion Js Scheduler is the complete solution for all applications that need to render interactive timetables, event schedules or appointment calendars. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. Find out more at https://mindfusion.eu/javascript-scheduler.html

    Interactive Calendar With Events In JavaScript

    In this blog post we will create a Google-like interactive monthly calendar where users will be able to create, edit and delete appointments in real time. We
    will use the JavaScript Scheduler. Here is a screenshot of the finished application:

    JavaScript Schedule That Mirrors the Google Calendar Features

    JavaScript Schedule That Mirrors the Google Calendar Features

    And you can run the sample online from this link.

    I. Project Setup

    We need a reference to the following file to start development:

    • MindFusion.Scheduling.js
    • light.css

    The JavaScript file provides the scheduling functionality. The CSS file is responsible for the styling of our calendar. We create a subfolder named “themes” and we place the light.css file there.

    We create an HTML file, a blank web page called GoogleSchedule and in the head section we place a reference to the two CSS file:

    <link href="themes/light.css" rel="stylesheet" />

     

    The reference to the JavaScript file goes at the bottom of the page, right before the closing body tag.

    <a href="http://MindFusion.Scheduling.js">http://MindFusion.Scheduling.js</a>

     

    We need a element that will represent the calendar, we create one in HTML code and assign it an id:

    <div id="calendar" style="height: 100%; width: 100%;"></div>
    

    We want the calendar to take the whole page, that’s why width and height are 100%.

    II. Create and Customize the Scheduler

    Now we are ready to do the real JavaScript programming of the calendar library. We create an empty JS file called “GoogleSchedule.js” and add a reference to it in the web page, at the bottom:

    <a href="http://GoogleSchedule.js">http://GoogleSchedule.js</a>

     

    In this JavaScript file we first create a mapping to the MindFusion.Scheduling namespace:

    var p = MindFusion.Scheduling;

     

    Then we create a Calendar instance using the Calendar DOM element from the web page:

    // create a new instance of the calendar 
    var calendar = new p.Calendar(document.getElementById("calendar"));

     

    We set the calendar view to CalendarView .SingleMonth, which means the calendar shows one month at a time. We also set the theme that we referenced in the CSS file:

    calendar.currentView = p.CalendarView.SingleMonth;
    calendar.theme = "light";

     

    Another customization we make – we use the itemSettings.titleFormat property to add a prefix before each event subject. The prefix is the start time of this event. here is how you set it:

    calendar.itemSettings.titleFormat = "%s[hh:mm tt] %h";

     

    Finally, we render the calendar:

    //visualize the calendar
    calendar.render();

     

    III. Custom Form

    By default, the form that renders when the user clicks on a cell or selection of cells in the calendar allows edit of the dates, but not hours. We will render our custom form, derived from BaseForm to change that. Our form will offer the users a list with hours for the selected dates.

    We create a new, empty JavaScript file “TimeForm.js”. There we override the constructor of the BaseForm:

     TimeForm = function (calendar, item, type)
    {
    	p.BaseForm.call(this, calendar, item);
    
    	this._id = "TimeForm";
    	this._type = type;
    	this.headerText = "Appointment";
    	
    }

     

    As you can see from the constructor each BaseForm provides data for the calendar and the item that is created or edited. We will use that information later on. We create a prototype of our form and assign the constructor:

    TimeForm.prototype = Object.create(p.BaseForm.prototype);
    TimeForm.prototype.constructor = TimeForm;

     

    TimeForm will be a simple one – it just renders a text area and two combo boxes with the possible hours for the start and end of the appointment. The combo boxes require a list with the members to be rendered. We create a list as a global variable:

    var hoursList;

     

    Then, in a new method we fill the list with the hours from 12 to 1, divided in intervals of 30 minutes:

    // create an array of objects to fill the hours drop-down
    TimeForm.prototype.getHourLabels = function ()
    {
    	hoursList = [];
    	hoursList.push({ value: 0, text: "12:00am" });
    	hoursList.push({ value: 1, text: "12:30am" });
    	
    	let index = 1;
    	
    	for(var i = 1; i &lt; 12; i++)
    	{
    		hoursList.push({ value: index+1, text: i.toString() + ":00am" });
    	    hoursList.push({ value: index+2, text: i.toString() + ":30am" });
    		
    		index += 2;
    	}
    	
    	//add the first afternnon hours
    	hoursList.push({ value: index + 1, text: "12:00pm" });
    	hoursList.push({ value: index + 2, text: "12:30pm" });
    	
    	index += 2;
    	
    	for(i = 1; i &lt; 12; i++)
    	{
    		hoursList.push({ value: index+1, text: i.toString() + ":00pm" });
    	    hoursList.push({ value: index+2, text: i.toString() + ":30pm" });
    		
    		index += 2;
    	}	
    	
    	return hoursList;
    }
    

     

    The next step is to override the drawContent function of BaseForm:

    TimeForm.prototype.drawContent = function ()
    {
    	p.BaseForm.prototype.drawContent.call(this);
    
    	var content = this.getContent();
    .....
    }

     

    First, we create the text area:

    var row = this.row();
    	row.innerHTML = this.localInfo.subjectCaption;
    	content.appendChild(row);
    	
    	// create a text-area for the item subject
    	var textArea = this.createTextArea({ id: "subject", initValue: this.item.subject, events: { keydown: this._areaKeyDown} });
    	textArea.element.style.width = "200px";
    	this.addControl(textArea);
    
    	row = this.row();
    	row.appendChild(textArea.element);
    	content.appendChild(row);

     

    Before the text area we place a label with “Subject” on it. The createTextArea method requires several parameters. The first one is the id, then the initial content to be rendered and the events. We want the text area to be 200px wide. The row element places a row of controls in the BaseForm. We use it every time we want to start a new row with elements.

    The text area reads its initial content from the value of the subject field in the item object that we receive as reference. After that we create a new row with elements: the drop-down with the hours for the start time:

           // create a drop-down list for start hours
    	row = this.row();
    	row.innerHTML = "Start Time";
    	content.appendChild(row);
    
    	var control = this.createDropDownList({ id: "start_time", items: this.getHourLabels(), initValue: this.getStartTimeIndex(), addEmptyValue: false });
    	control.element.style.width = "200px";
    	this.addControl(control);
    
    	row = this.row();
    	row.appendChild(control.element);
    	content.appendChild(row);
    

     

    The code is almost identical to the code for the text area, but here we call the getHourLabels method that returns the array with time values. There is one other new method: getStartTimeIndex(). It’s task is to check the start time of the item and to set the initial value of the drop-down control to that time.

    Here is the method:

    // get the index of the current item's index to set the value of the startTime drop-down:
    TimeForm.prototype.getStartTimeIndex = function ()
    {
    	if (this.item != null &amp;&amp; this.item.startTime != null)
    	{
    		
    		let index  = this.item.startTime.__getHours() * 2;
    		if(this.item.startTime.__getMinutes() &gt; 0)
    			index++;
    		return index;		
    		
    	}
    	return -1;
    }

     

    The method checks the hour value of the start time and multiplies it by two because for each hour we show two values in the drop-down: 9:00 and 9:30. If the user has selected half an hour we increment the index with 1.
    We use almost the same code to create the endTime drop-down control, so we won’t discuss it here. You can check its code from the download with the source code files for this sample.

    Our form needs two buttons – Save and Cancel. We create them in the drawButtons method:

    // override BaseForm's drawButtons method to create form buttons
    TimeForm.prototype.drawButtons = function ()
    {
    	var thisObj = this;
    
    	var btnSave = this.createButton({
    		id: "btnSave",
    		text: this.localInfo.saveButtonCaption,
    		events: { "click": function click(e)
    		{
    			return thisObj.onSaveButtonClick(e);
    		}
    		}
    	});
    
    	var btnCancel = this.createButton({
    		id: "btnCancel",
    		text: this.localInfo.cancelButtonCaption,
    		events: { click: function click(e)
    		{
    			return thisObj.onCancelButtonClick(e);
    		}
    		}
    	});
    
    	var buttons = this.row();
    	buttons.classList.add("mfp-buttons-row");
    	buttons.appendChild(btnSave.element);
    	buttons.appendChild(btnCancel.element);
    
    	return buttons;
    };

     

    The BaseForm.createButton() method is similar to the methods that create text area and drop-down lists. We specify here that we will handle the click event for the two buttons. We place the buttons in a new row. Note that you don’t have to call the createButtons function anywhere – it is called automatically by BaseForm.

    What happens when the user presses “Save”? Well, we’ll have to read the data from the hour drop-down controls and adjust the start and end time of the newly created Item:

    TimeForm.prototype.onSaveButtonClick = function (e)
    {
    	// update the item with the form data
    	 // update the item with the form data
       var startIndex = +this.getControlValue("start_time");
       var startTime = this.item.startTime.date.clone().addHours(startIndex * 0.5);
    
       var endIndex = +this.getControlValue("end_time");
       var endTime = this.item.endTime.date.clone().addHours(endIndex * 0.5);
    
       // if end time is specified, decrease it by one day
       if (endIndex != 0 &amp;&amp; this.item.endTime.hour == 0)
        endTime.addDays(-1);
    
       // check for inconsistent start/end time
       if (startTime.valueOf() &gt; endTime.valueOf())
             endTime = startTime.clone().addHours(1);
    
       // apply changes 
       this.item.subject = this.getControlValue("subject"); 
       this.item.startTime = startTime;
       this.item.endTime = endTime;
    
       // if a new item is created, add it to the schedule.items collection
       if (this.type === "new")
         this.calendar.schedule.items.add(this.item);
    
       // close the form
       this.closeForm();
    
       // repaint the calendar
       this.calendar.repaint(true);
    };
    

    First, we get the value of the startTime drop-down list and we calculate the amount of time to add to the startTime of an Item. A new Item always has a startTime at midnight. Then, we check the number of days the user has selected and calculate how many hours the event actually takes. We assign end time to a copy of the start time and add the calculated event duration to the value. Finally, if the event is new – we add it to the collection of item sin the schedule, if it’s old – we correct its data. Then we close the form and repaint the calendar.

    IV. Using the Custom TimeForm

    In order to use our custom form we have to add a reference to it in the HTML page, as we did with the other two files:

    <script src="TimeForm.js" type="text/javascript"></script>

     

    Then we edit the GoogleSchedule.js file First, we need to disable the built-in forms with the useForms property.

    // disable this built-in forms for item creation and modification
    calendar.useForms = false;

     

    Then we have to handle the onSelectionEnd and onItemDoubleClick events to render our form. First, we wire up the events:

    // handle the itemDoubleClick event to show the custom form for item editing
    calendar.itemDoubleClick.addEventListener(handleItemDoubleClick);
    
    // handle the selectionEnd event to show the custom form for item creation
    calendar.selectionEnd.addEventListener(handleSelectionEnd);

     

    Then we render the forms, below is the code that shows the TimeForm when a new item is created:

    function handleSelectionEnd(sender, args)
    {
    	// create a new item with the start and end time of the selection
    	var item = new p.Item();
    	item.startTime = args.startTime;
    	item.endTime = args.endTime;
    	
    	// create and show the custom form
    	var form = new TimeForm(sender, item, "new");
    	form.showForm();
    }

     

    We copy the start and end time of the selection from the event arguments. Then we use them in the constructor of the BaseForm.

    And that’s the end of this tutorial. Here is a link to download the complete source code of the sample:

    Download the Google Calendar in JavaScript Sample

    About MindFusion JavaScript Scheduler: MindFusion Js Scheduler is the complete solution for all applications that need to render interactive timetables, event schedules or appointment calendars. Fully responsive, highly customizable and easy to integrate, you can quickly program the JavaScript scheduling library according to your needs. Find out more at https://mindfusion.eu/javascript-scheduler.html

    Ticket Booking System (Continued)

    In part I of the Ticket Booking System blog post we discussed the controls used in the software and how we generate and arrange the hall seats. Now let’s get deeper into the details on how we retrieve the data and how we customize the controls.

    We use the Entity Framework and the Entity Data Model wizard to connect to our MS SQL database and retrieve the ticket data. Here is the model of the database:

    Event Booking Software: MS SQL Database Model

    Event Booking Software: MS SQL Database Model

    I. The Database

    We have a table for the event type (ballet, concert, opera etc.), a table for the events (Swan Lake ballet, Mozart concert, La Traviata oepra etc.), a table for the performances (an event with a date) and a table for the tickets that were sold. The performance table has a column for the base price of the tickets. The hall is divided into 3 sections according to the price of the tickets – the Performance table stores the price for the cheapest category. The other two categories are calculated according to the base price.

    II. Events

    We keep a class variable for the EventsTicketsEntities, which we initialize in the Form1 constructor:

    
    public partial class Form1 : Form
    {
       EventsTicketsEntities records;
       double basePrice;
    
       public Form1()
       {
          InitializeComponent();
          records = new EventsTicketsEntities();
          .................
    }
    
    

    The events are instances of the Appointment class of the Calendar. Here is the method that we use to create the Appointment-s based on the data from the database:

    
    private void loadEvents()
    {         
    
      List performances = records.Performances.ToList();     
    
      foreach (Performance p in performances)
       {
          Appointment app = new Appointment();
          app.StartTime = (DateTime)p.Date;
          app.EndTime = app.StartTime.AddHours(2.0);           
          app.HeaderText = "";
          app.DescriptionText = p.Event.Title;
          app.Tag = p.Event.EventType_Id;
          app.Style.Brush = getBrush((int)app.Tag);
          calendar.Schedule.Items.Add(app);
    
         }
    }
    	
    

    We read all records in the Performances table and create an Appointment for each one. The start date of the event is the field from the database. We add to it 2 hours as duration, otherwise the event wouldn’t show up. The brush of the Appointment depends on the type of the event. The appointment does not show any text, but the event title serves as a description. As a rule the calendar control renders an Appointment‘s description as a tooltip when the user hovers the item.

    The schedule item description is rendered as a tooltip

    The schedule item description is rendered as a tooltip

    III. Hall Seats

    In order to identify the location of a seat we assign an instance of the Seat structure as an Id to the ShapeNode that represents the seat.

    public struct Seat
    {
      public Seat (int row, int column)
       {
         this.Row = row;
         this.Place = column;
       }
    
      public int Row
       {
         get; set; 
       }
    
     public int Place
       {
           get; set;
       }
    
    }
    

    We also include a rowStart parameter in the CreateSection method. The parameter keeps track of the total count of seats being generated. This allows each seat to have a unique row number:

    	
    
    void CreateSection(int rowStart, int[] seatsPerRow,
        float topY, float seatWidth, float seatHeight,
         float xPadding, float yPadding, float arcRadius)
    {
            .................		
     
            seat.Id = new Seat(rowStart + r, s);
            seat.Tag = calcSeatCoeff((Seat)seat.Id);	
    
    }
    
    

    The Seat tag of the ShapeNode is calculated based on its location in the hall. It is the coefficient, which multiplied by the base price for this performance gives us the final price for this seat.

    Each time a new performance is selected on the calendar, our application must refresh the seat info. Here is the method that takes care of the seat colors:

    //clears the X sign at an occupied seat
    private void updateSeats( double basePrice )
    {
      foreach( var seat in diagram.Nodes)
      {
         (seat as ShapeNode).Text = "";
         if (seat.Tag != null)
          {
            seat.Brush = getSeatBrush(basePrice * (double)seat.Tag);
           }
      }
    }
    

    The method calculates the price of the seat and checks the color that corresponds to this price. Whenever a seat is clicked, the application marks it as selected. This is done by drawing an “X” as text on the ShapeNode using a large Font size:

    Seat seatInfo = (Seat)seat.Id;
    TICKETS_SOLD _ticket = new TICKETS_SOLD() { };
    _ticket.Id = records.TICKETS_SOLD.ToList().Count;
    _ticket.Performance_Id = (int)calendar.Tag;
    _ticket.Row_Index = seatInfo.Row;
    _ticket.Seat_Index = seatInfo.Place;
    records.TICKETS_SOLD.Add(_ticket);
                            
    try
        {
          records.SaveChanges();
    
        }
    catch (DbEntityValidationException ex)
        {
          Debug.WriteLine(ex.Message);
        }
        seat.Text = "X";
    

    We create a new TICKETS_SOLD record, which contains a unique Id for the sold ticket, an Id for the performance, and the location of the seat (row and column). There is something more to that. When the user tries to click on a seat that is already sold we want to warn him that it is not possible to buy the seat. This is done by having a special node that stays hidden and shows up for a few seconds only to warn the user:

    private void generateOccupiedNode()
      {
        float x = diagram.Bounds.Left + diagram.Bounds.Width / 2 - 50;
        float y = diagram.Bounds.Top + diagram.Bounds.Height / 2 - 30;
    
        RectangleF nodeBounds = new RectangleF(x, y, 100, 60);
        ShapeNode node = diagram.Factory.CreateShapeNode(nodeBounds);
        node.Brush = new MindFusion.Drawing.SolidBrush(Color.FromArgb(100, 206, 0, 0));            
        node.Font = new Font("Arial", 26);
        node.TextBrush = new MindFusion.Drawing.SolidBrush(Color.Black);
        node.Visible = false;
        node.Shape = Shapes.RoundRect;
        node.Id = "Occupied";
    
      }
    		
    

    The seat is rendered in the middle of the diagram’s visible area and has a semi – transparent background. We use a timer to track the seconds when the node is displayed:

    
    private void diagram_NodeClicked(object sender, NodeEventArgs e)
     {
       ShapeNode seat = e.Node as ShapeNode;
       if(seat != null)
         {
           if(seat.Text == "X")
            {
               ShapeNode warning = (ShapeNode)diagram.FindNodeById("Occupied");
    
              if(warning != null)
              {
                 warning.Text = "This Seat is Occupied!";
                 Timer timer = new Timer();
                 timer.Interval = 2500;
                 timer.Tick += Timer_Tick;
                 warning.Visible = true;
                 timer.Start();
              }
            }
    	...........
    	
    }
    

    We then find the node and make it invisible again:

    
    private void Timer_Tick(object sender, EventArgs e)
      {
        ShapeNode warning = (ShapeNode)diagram.FindNodeById("Occupied");
        warning.Visible = false;
    }
         
    

    With this we have covered the basic methods that build the Event Ticket Reservation Software. Here is the final version:

    Event Booking System in WinForms

    Event Booking System in WinForms

    The full source code of the application together with the sample database is available for direct download from here:

    Event Ticket Booking System – Download

    The sample uses the Diagramming and Scheduling controls from the MindFusion WinForms Pack. If you have questions regarding the sample or the components do not hesitate to post them on the MindFusion discussion board.